diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..77041210ee --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,23 @@ +version: 2 +updates: +- package-ecosystem: maven + directory: / + ignore: + - dependency-name: "org.kaazing:k3po.*" + versions: [ "4.x", "5.x" ] + - dependency-name: "com.guicedee.services:commons-*" + versions: [ "62" ] + schedule: + interval: daily +- package-ecosystem: docker + directory: /cloud/docker-image/src/main/docker/release + schedule: + interval: daily +- package-ecosystem: docker + directory: /cloud/docker-image/src/main/docker/incubator + schedule: + interval: daily +- package-ecosystem: github-actions + directory: / + schedule: + interval: daily diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 353ebfc537..d87d467656 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,17 +13,18 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 11, 17 ] + java: [ 11, 17, 20 ] steps: - name: Checkout GitHub sources - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup JDK ${{ matrix.java }} - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: + distribution: zulu java-version: ${{ matrix.java }} - name: Cache Maven packages - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.m2/repository diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..d790178a93 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,91 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: CodeQL + +on: + push: + branches: [ "develop", "main" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "develop" ] + schedule: + - cron: '27 10 * * 4' + +jobs: + analyze: + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # Cache downloaded Maven dependencies + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: | + ~/.m2/repository + !~/.m2/repository/io/aklivity/zilla + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 59ce113780..2e76e189d2 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,2 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/CHANGELOG.md b/CHANGELOG.md index 10e376ed00..e0f3fa5c3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,126 @@ ## [Unreleased](https://github.com/aklivity/zilla/tree/HEAD) -[Full Changelog](https://github.com/aklivity/zilla/compare/0.9.50...HEAD) +[Full Changelog](https://github.com/aklivity/zilla/compare/0.9.51...HEAD) + +**Implemented enhancements:** + +- Connection pool for `kafka` binding `heartbeat` requests [\#462](https://github.com/aklivity/zilla/issues/462) +- Enhance `mqtt` binding configuration syntax [\#420](https://github.com/aklivity/zilla/issues/420) +- Mqtt-Kafka session implementation [\#319](https://github.com/aklivity/zilla/issues/319) +- Design `zilla.yaml` configuration syntax for schema types [\#310](https://github.com/aklivity/zilla/issues/310) +- Generate `zilla.yaml` from `AsyncAPI` specification [\#256](https://github.com/aklivity/zilla/issues/256) +- Generate `zilla.yaml` from `OpenAPI` specification\(s\) [\#254](https://github.com/aklivity/zilla/issues/254) +- Support `kafka` consumer groups [\#215](https://github.com/aklivity/zilla/issues/215) +- MQTT guard implementation [\#307](https://github.com/aklivity/zilla/pull/307) ([bmaidics](https://github.com/bmaidics)) + +**Fixed bugs:** + +- Zilla crash during attempted WebSocket connection [\#391](https://github.com/aklivity/zilla/issues/391) +- Index out of bounds exception with HTTP-Kafka proxy [\#293](https://github.com/aklivity/zilla/issues/293) + +**Closed issues:** + +- Send will message as data frame + reject large packets [\#364](https://github.com/aklivity/zilla/issues/364) +- Support Kafka client request-response with MQTT clients [\#326](https://github.com/aklivity/zilla/issues/326) +- Add guard support for MQTT binding [\#308](https://github.com/aklivity/zilla/issues/308) +- Implement retained feature for mqtt-kafka [\#289](https://github.com/aklivity/zilla/issues/289) + +**Merged pull requests:** + +- Mqtt client publish fix [\#464](https://github.com/aklivity/zilla/pull/464) ([bmaidics](https://github.com/bmaidics)) +- Fix implicit subscribe no packetId reconnection [\#451](https://github.com/aklivity/zilla/pull/451) ([bmaidics](https://github.com/bmaidics)) +- Remove clientId from subscribeKey [\#450](https://github.com/aklivity/zilla/pull/450) ([bmaidics](https://github.com/bmaidics)) +- Rename config command to generate [\#449](https://github.com/aklivity/zilla/pull/449) ([attilakreiner](https://github.com/attilakreiner)) +- Do not include generated subcsriptionId [\#448](https://github.com/aklivity/zilla/pull/448) ([bmaidics](https://github.com/bmaidics)) +- Adjust engine backoff strategy configuration [\#446](https://github.com/aklivity/zilla/pull/446) ([jfallows](https://github.com/jfallows)) +- Don't close group stream on cluster and describe streams closer [\#444](https://github.com/aklivity/zilla/pull/444) ([akrambek](https://github.com/akrambek)) +- Engine configuration worker capacity [\#443](https://github.com/aklivity/zilla/pull/443) ([jfallows](https://github.com/jfallows)) +- Remove unused engine configuration [\#442](https://github.com/aklivity/zilla/pull/442) ([jfallows](https://github.com/jfallows)) +- Ensure socket channel has finished connecting before attempting to read [\#441](https://github.com/aklivity/zilla/pull/441) ([jfallows](https://github.com/jfallows)) +- Mqtt subscription handling bugfix [\#439](https://github.com/aklivity/zilla/pull/439) ([bmaidics](https://github.com/bmaidics)) +- Connection pool for kafka group client [\#438](https://github.com/aklivity/zilla/pull/438) ([akrambek](https://github.com/akrambek)) +- Add affinity to mqtt server and client binding [\#436](https://github.com/aklivity/zilla/pull/436) ([bmaidics](https://github.com/bmaidics)) +- Set init flag for data fragmentation in grpc [\#431](https://github.com/aklivity/zilla/pull/431) ([akrambek](https://github.com/akrambek)) +- Fix flow control issue in kafka-grpc [\#430](https://github.com/aklivity/zilla/pull/430) ([akrambek](https://github.com/akrambek)) +- Fix known issues in group client [\#428](https://github.com/aklivity/zilla/pull/428) ([akrambek](https://github.com/akrambek)) +- Enhance mqtt binding configuration syntax [\#425](https://github.com/aklivity/zilla/pull/425) ([bmaidics](https://github.com/bmaidics)) +- Buffer fragmented kafka session signal messages [\#424](https://github.com/aklivity/zilla/pull/424) ([bmaidics](https://github.com/bmaidics)) +- Fix flow control bug [\#423](https://github.com/aklivity/zilla/pull/423) ([akrambek](https://github.com/akrambek)) +- Serverref change [\#422](https://github.com/aklivity/zilla/pull/422) ([bmaidics](https://github.com/bmaidics)) +- Fix finding next partition id [\#419](https://github.com/aklivity/zilla/pull/419) ([akrambek](https://github.com/akrambek)) +- Don't end subscribe stream when unsubscribe, no subscription [\#418](https://github.com/aklivity/zilla/pull/418) ([bmaidics](https://github.com/bmaidics)) +- Remove default kafka topic names [\#416](https://github.com/aklivity/zilla/pull/416) ([bmaidics](https://github.com/bmaidics)) +- Fix consumer assignment causing decoding issue [\#414](https://github.com/aklivity/zilla/pull/414) ([akrambek](https://github.com/akrambek)) +- Add test to validate merge produce rejection on wrong partition [\#410](https://github.com/aklivity/zilla/pull/410) ([akrambek](https://github.com/akrambek)) +- Consumer related bug fixes [\#405](https://github.com/aklivity/zilla/pull/405) ([akrambek](https://github.com/akrambek)) +- Remove unused extends OptionsConfig from non-options config classes [\#403](https://github.com/aklivity/zilla/pull/403) ([jfallows](https://github.com/jfallows)) +- Support consumer protocol [\#400](https://github.com/aklivity/zilla/pull/400) ([akrambek](https://github.com/akrambek)) +- Mqtt client implementation [\#398](https://github.com/aklivity/zilla/pull/398) ([bmaidics](https://github.com/bmaidics)) +- Support build after local docker zpm install [\#396](https://github.com/aklivity/zilla/pull/396) ([jfallows](https://github.com/jfallows)) +- Adapt to consumer group changes [\#394](https://github.com/aklivity/zilla/pull/394) ([bmaidics](https://github.com/bmaidics)) +- Bump actions/checkout from 3 to 4 [\#393](https://github.com/aklivity/zilla/pull/393) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Merged consumer group support [\#390](https://github.com/aklivity/zilla/pull/390) ([akrambek](https://github.com/akrambek)) +- Session expiry [\#387](https://github.com/aklivity/zilla/pull/387) ([bmaidics](https://github.com/bmaidics)) +- Request data length is non-negative [\#386](https://github.com/aklivity/zilla/pull/386) ([jfallows](https://github.com/jfallows)) +- Fix mqtt-kafka publish bug [\#383](https://github.com/aklivity/zilla/pull/383) ([bmaidics](https://github.com/bmaidics)) +- Support configuration property definitions for custom type... [\#382](https://github.com/aklivity/zilla/pull/382) ([jfallows](https://github.com/jfallows)) +- Mqtt kafka redirect [\#381](https://github.com/aklivity/zilla/pull/381) ([bmaidics](https://github.com/bmaidics)) +- Bump org.apache.ivy:ivy from 2.5.1 to 2.5.2 in /manager [\#377](https://github.com/aklivity/zilla/pull/377) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Generate zilla.yaml for asyncapi.mqtt.proxy from an AsyncAPI definition [\#375](https://github.com/aklivity/zilla/pull/375) ([attilakreiner](https://github.com/attilakreiner)) +- Review budget debitors [\#374](https://github.com/aklivity/zilla/pull/374) ([jfallows](https://github.com/jfallows)) +- Support binding config builder exit [\#373](https://github.com/aklivity/zilla/pull/373) ([jfallows](https://github.com/jfallows)) +- Support config builder for MQTT config [\#372](https://github.com/aklivity/zilla/pull/372) ([jfallows](https://github.com/jfallows)) +- Bump org.codehaus.mojo:exec-maven-plugin from 1.6.0 to 3.1.0 [\#370](https://github.com/aklivity/zilla/pull/370) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Generate zilla.yaml from an AsyncAPI definition [\#369](https://github.com/aklivity/zilla/pull/369) ([attilakreiner](https://github.com/attilakreiner)) +- Mqtt kafka will message delivery [\#367](https://github.com/aklivity/zilla/pull/367) ([bmaidics](https://github.com/bmaidics)) +- Bump org.apache.maven.plugins:maven-plugin-plugin from 3.5 to 3.9.0 [\#366](https://github.com/aklivity/zilla/pull/366) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump junit:junit from 4.13.1 to 4.13.2 [\#365](https://github.com/aklivity/zilla/pull/365) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Send will message as data frame + reject large packets [\#363](https://github.com/aklivity/zilla/pull/363) ([bmaidics](https://github.com/bmaidics)) +- Sanitize zip entry path [\#362](https://github.com/aklivity/zilla/pull/362) ([jfallows](https://github.com/jfallows)) +- Bump org.apache.maven:maven-core from 3.6.0 to 3.8.1 [\#361](https://github.com/aklivity/zilla/pull/361) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Merge consumer group metadata [\#359](https://github.com/aklivity/zilla/pull/359) ([akrambek](https://github.com/akrambek)) +- Support dynamic behavior injection in config builder fluent API [\#358](https://github.com/aklivity/zilla/pull/358) ([jfallows](https://github.com/jfallows)) +- Bump org.apache.maven.plugins:maven-jar-plugin from 3.2.0 to 3.3.0 [\#357](https://github.com/aklivity/zilla/pull/357) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump com.squareup:javapoet from 1.9.0 to 1.13.0 [\#355](https://github.com/aklivity/zilla/pull/355) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Include JDK 20 in build matrix [\#352](https://github.com/aklivity/zilla/pull/352) ([jfallows](https://github.com/jfallows)) +- Ignore CacheFetchIT.shouldFetchFilterSyncWithData [\#351](https://github.com/aklivity/zilla/pull/351) ([attilakreiner](https://github.com/attilakreiner)) +- Metadata for group merged stream [\#349](https://github.com/aklivity/zilla/pull/349) ([akrambek](https://github.com/akrambek)) +- Bump io.fabric8:docker-maven-plugin from 0.39.1 to 0.43.2 [\#348](https://github.com/aklivity/zilla/pull/348) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump org.sonatype.plexus:plexus-sec-dispatcher from 1.3 to 1.4 [\#347](https://github.com/aklivity/zilla/pull/347) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump io.kokuwa.maven:helm-maven-plugin from 6.6.0 to 6.10.0 [\#345](https://github.com/aklivity/zilla/pull/345) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump org.apache.maven.plugin-tools:maven-plugin-annotations from 3.5 to 3.9.0 [\#344](https://github.com/aklivity/zilla/pull/344) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump alpine from 3.18.2 to 3.18.3 in /cloud/docker-image/src/main/docker/release [\#343](https://github.com/aklivity/zilla/pull/343) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump eclipse-temurin from 17-alpine to 20-alpine in /cloud/docker-image/src/main/docker/incubator [\#342](https://github.com/aklivity/zilla/pull/342) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump alpine from 3.18.2 to 3.18.3 in /cloud/docker-image/src/main/docker/incubator [\#341](https://github.com/aklivity/zilla/pull/341) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump eclipse-temurin from 17-alpine to 20-alpine in /cloud/docker-image/src/main/docker/release [\#340](https://github.com/aklivity/zilla/pull/340) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump org.apache.maven.plugins:maven-compiler-plugin from 3.8.0 to 3.11.0 [\#339](https://github.com/aklivity/zilla/pull/339) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump actions/setup-java from 1 to 3 [\#338](https://github.com/aklivity/zilla/pull/338) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump actions/checkout from 2 to 3 [\#337](https://github.com/aklivity/zilla/pull/337) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump actions/cache from 2 to 3 [\#336](https://github.com/aklivity/zilla/pull/336) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump org.moditect:moditect-maven-plugin from 1.0.0.RC1 to 1.0.0.Final [\#335](https://github.com/aklivity/zilla/pull/335) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump com.mycila:license-maven-plugin from 4.1 to 4.2 [\#334](https://github.com/aklivity/zilla/pull/334) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump org.apache.maven.plugins:maven-source-plugin from 3.0.1 to 3.3.0 [\#333](https://github.com/aklivity/zilla/pull/333) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump byteman.version from 4.0.20 to 4.0.21 [\#332](https://github.com/aklivity/zilla/pull/332) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Bump antlr4.version from 4.11.1 to 4.13.0 [\#331](https://github.com/aklivity/zilla/pull/331) ([dependabot[bot]](https://github.com/apps/dependabot)) +- Config builders [\#330](https://github.com/aklivity/zilla/pull/330) ([jfallows](https://github.com/jfallows)) +- Add hashKey support to merged stream [\#329](https://github.com/aklivity/zilla/pull/329) ([bmaidics](https://github.com/bmaidics)) +- Default group session timeout [\#328](https://github.com/aklivity/zilla/pull/328) ([akrambek](https://github.com/akrambek)) +- Include member count as part of group data ex [\#327](https://github.com/aklivity/zilla/pull/327) ([akrambek](https://github.com/akrambek)) +- Request-response mqtt-kafka [\#325](https://github.com/aklivity/zilla/pull/325) ([bmaidics](https://github.com/bmaidics)) +- Generate zilla.yaml from an OpenAPI definition [\#324](https://github.com/aklivity/zilla/pull/324) ([attilakreiner](https://github.com/attilakreiner)) +- Support zilla.yaml config reader and writer [\#323](https://github.com/aklivity/zilla/pull/323) ([jfallows](https://github.com/jfallows)) +- Ignore heartbeat if the handshake request hasn't completed yet [\#322](https://github.com/aklivity/zilla/pull/322) ([akrambek](https://github.com/akrambek)) +- Support local zpmw install [\#321](https://github.com/aklivity/zilla/pull/321) ([jfallows](https://github.com/jfallows)) +- Mqtt kafka sessions [\#318](https://github.com/aklivity/zilla/pull/318) ([bmaidics](https://github.com/bmaidics)) +- Mqtt kafka options [\#304](https://github.com/aklivity/zilla/pull/304) ([bmaidics](https://github.com/bmaidics)) +- Redirect on mqtt reset using server reference [\#303](https://github.com/aklivity/zilla/pull/303) ([bmaidics](https://github.com/bmaidics)) +- Mqtt retained feature [\#290](https://github.com/aklivity/zilla/pull/290) ([bmaidics](https://github.com/bmaidics)) +- Support Kafka consumer groups [\#262](https://github.com/aklivity/zilla/pull/262) ([akrambek](https://github.com/akrambek)) + +## [0.9.51](https://github.com/aklivity/zilla/tree/0.9.51) (2023-07-27) + +[Full Changelog](https://github.com/aklivity/zilla/compare/0.9.50...0.9.51) **Implemented enhancements:** diff --git a/README.md b/README.md index 2e5a62fdfe..a641c56cbf 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Zilla abstracts Apache Kafka® for web applications, IoT clients and microservic Zilla has no external dependencies and does not rely on the Kafka Consumer/Producer API or Kafka Connect. Instead, it natively supports the Kafka wire protocol and uses advanced protocol mediation to establish stateless API entry points into Kafka. Zilla also addresses security enforcement, observability and connection offloading on the data path. -When Zilla is deployed alongside Apache Kafka®, achieving an extensible yet streamlined event-driven architecture becomes much easier. +When Zilla is deployed alongside Apache Kafka®, achieving an extensible yet streamlined event-driven architecture becomes possible. ## Contents diff --git a/build/flyweight-maven-plugin/pom.xml b/build/flyweight-maven-plugin/pom.xml index 2ed41013c9..5b1b1c4b68 100644 --- a/build/flyweight-maven-plugin/pom.xml +++ b/build/flyweight-maven-plugin/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla build - 0.9.51 + 0.9.52 ../pom.xml diff --git a/build/flyweight-maven-plugin/src/main/java/io/aklivity/zilla/build/maven/plugins/flyweight/internal/generate/Varuint32FlyweightGenerator.java b/build/flyweight-maven-plugin/src/main/java/io/aklivity/zilla/build/maven/plugins/flyweight/internal/generate/Varuint32FlyweightGenerator.java index 3552737de1..b5f7ea0166 100644 --- a/build/flyweight-maven-plugin/src/main/java/io/aklivity/zilla/build/maven/plugins/flyweight/internal/generate/Varuint32FlyweightGenerator.java +++ b/build/flyweight-maven-plugin/src/main/java/io/aklivity/zilla/build/maven/plugins/flyweight/internal/generate/Varuint32FlyweightGenerator.java @@ -233,9 +233,9 @@ private MethodSpec setMethod() .addModifiers(PUBLIC) .returns(flyweightType.nestedClass("Builder")) .addParameter(int.class, "value") - .beginControlFlow("if (value > 0x0FFFFFFF)") + .beginControlFlow("if (value < 0)") .addStatement("throw new $T(String.format($S, value))", IllegalArgumentException.class, - "Input value %d too long") + "Input value %d is negative") .endControlFlow() .addStatement("final MutableDirectBuffer buffer = buffer()") .addStatement("int progress = offset()") diff --git a/build/pom.xml b/build/pom.xml index dda4af3ceb..59ebf8517e 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla zilla - 0.9.51 + 0.9.52 ../pom.xml diff --git a/cloud/docker-image/pom.xml b/cloud/docker-image/pom.xml index 59fc9256c4..ee84364032 100644 --- a/cloud/docker-image/pom.xml +++ b/cloud/docker-image/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla cloud - 0.9.51 + 0.9.52 ../pom.xml @@ -73,6 +73,12 @@ ${project.version} runtime + + ${project.groupId} + binding-mqtt + ${project.version} + runtime + ${project.groupId} binding-sse @@ -115,6 +121,12 @@ ${project.version} runtime + + ${project.groupId} + binding-mqtt-kafka + ${project.version} + runtime + ${project.groupId} binding-sse-kafka @@ -201,14 +213,18 @@ src/main/docker/*/zpmw + src/main/docker/*/zilla src/main/docker/*/zilla.properties + src/main/docker/*/.zilla/** + src/main/docker/*/zpm.json.template + src/main/docker/*/zpm.json + src/main/docker/*/.zpm/** org.codehaus.mojo exec-maven-plugin - 3.0.0 ${project.groupId} @@ -233,7 +249,7 @@ io.fabric8 docker-maven-plugin - 0.39.1 + 0.43.2 ${*} @@ -270,6 +286,9 @@ io/aklivity/zilla/manager/** io/aklivity/zilla/incubator/** org/agrona/** + org/apache/apache/** + org/apache/maven/maven/** + org/apache/maven/maven-parent/** jakarta/json/** jakarta/inject/** org/leadpony/justify/** @@ -285,6 +304,10 @@ org/slf4j/** org/antlr/** org/sonatype/oss/** + com/fasterxml/oss-parent/** + com/fasterxml/jackson/** + org/yaml/snakeyaml/** + org/junit/** @@ -326,31 +349,25 @@ ${project.groupId} - binding-mqtt - ${project.version} - runtime - - - ${project.groupId} - binding-mqtt-kafka + command-dump ${project.version} runtime ${project.groupId} - command-dump + command-tune ${project.version} runtime ${project.groupId} - command-tune + exporter-otlp ${project.version} runtime ${project.groupId} - exporter-otlp + command-config ${project.version} runtime diff --git a/cloud/docker-image/src/main/docker/.gitignore b/cloud/docker-image/src/main/docker/.gitignore index e52b514a42..9b5c9c3e77 100644 --- a/cloud/docker-image/src/main/docker/.gitignore +++ b/cloud/docker-image/src/main/docker/.gitignore @@ -1,2 +1,5 @@ zpmw - +zpm.json +zpm-lock.json +zilla.yaml +tls/ diff --git a/cloud/docker-image/src/main/docker/incubator/Dockerfile b/cloud/docker-image/src/main/docker/incubator/Dockerfile index 6babc87b1e..78e73cc2dd 100644 --- a/cloud/docker-image/src/main/docker/incubator/Dockerfile +++ b/cloud/docker-image/src/main/docker/incubator/Dockerfile @@ -13,12 +13,12 @@ # specific language governing permissions and limitations under the License. # -FROM eclipse-temurin:17-alpine AS build +FROM eclipse-temurin:20-alpine AS build COPY maven /root/.m2/repository COPY zpmw zpmw -COPY zpm.json zpm.json.template +COPY zpm.json.template zpm.json.template RUN apk add --no-cache gettext RUN cat zpm.json.template | env VERSION=${project.version} envsubst > zpm.json @@ -27,7 +27,7 @@ RUN apk add --no-cache wget RUN ./zpmw install --debug --exclude-remote-repositories RUN ./zpmw clean --keep-image -FROM alpine +FROM alpine:3.18.3 COPY --from=build /.zpm /opt/zilla/.zpm COPY --from=build /zilla /opt/zilla/zilla diff --git a/cloud/docker-image/src/main/docker/incubator/README.md b/cloud/docker-image/src/main/docker/incubator/README.md new file mode 100644 index 0000000000..5dc79cfcf6 --- /dev/null +++ b/cloud/docker-image/src/main/docker/incubator/README.md @@ -0,0 +1,13 @@ +### Running locally + +```bash +cat zpm.json.template | env VERSION=develop-SNAPSHOT envsubst > zpm.json +``` + +```bash +./zpmw install --debug --exclude-remote-repositories +``` + +``` +./zilla start --config +``` diff --git a/cloud/docker-image/src/main/docker/incubator/zpm.json b/cloud/docker-image/src/main/docker/incubator/zpm.json deleted file mode 100644 index cfef01d5db..0000000000 --- a/cloud/docker-image/src/main/docker/incubator/zpm.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "repositories": - [ - "https://maven.packages.aklivity.io/", - "https://repo.maven.apache.org/maven2/" - ], - - "imports": - [ - "io.aklivity.zilla:runtime:${VERSION}", - "io.aklivity.zilla:incubator:${VERSION}" - ], - - "dependencies": - [ - "io.aklivity.zilla:binding-amqp", - "io.aklivity.zilla:binding-echo", - "io.aklivity.zilla:binding-fan", - "io.aklivity.zilla:binding-filesystem", - "io.aklivity.zilla:binding-http", - "io.aklivity.zilla:binding-http-filesystem", - "io.aklivity.zilla:binding-http-kafka", - "io.aklivity.zilla:binding-grpc", - "io.aklivity.zilla:binding-grpc-kafka", - "io.aklivity.zilla:binding-kafka-grpc", - "io.aklivity.zilla:binding-kafka", - "io.aklivity.zilla:binding-mqtt", - "io.aklivity.zilla:binding-mqtt-kafka", - "io.aklivity.zilla:binding-proxy", - "io.aklivity.zilla:binding-sse", - "io.aklivity.zilla:binding-sse-kafka", - "io.aklivity.zilla:binding-tcp", - "io.aklivity.zilla:binding-tls", - "io.aklivity.zilla:binding-ws", - "io.aklivity.zilla:command", - "io.aklivity.zilla:command-dump", - "io.aklivity.zilla:command-metrics", - "io.aklivity.zilla:command-start", - "io.aklivity.zilla:command-stop", - "io.aklivity.zilla:command-tune", - "io.aklivity.zilla:engine", - "io.aklivity.zilla:exporter-prometheus", - "io.aklivity.zilla:exporter-otlp", - "io.aklivity.zilla:guard-jwt", - "io.aklivity.zilla:metrics-stream", - "io.aklivity.zilla:metrics-http", - "io.aklivity.zilla:metrics-grpc", - "io.aklivity.zilla:vault-filesystem", - "org.slf4j:slf4j-simple", - "org.antlr:antlr4-runtime" - ] -} diff --git a/cloud/docker-image/src/main/docker/incubator/zpm.json.template b/cloud/docker-image/src/main/docker/incubator/zpm.json.template new file mode 100644 index 0000000000..f50046cb33 --- /dev/null +++ b/cloud/docker-image/src/main/docker/incubator/zpm.json.template @@ -0,0 +1,53 @@ +{ + "repositories": + [ + "https://maven.packages.aklivity.io/", + "https://repo.maven.apache.org/maven2/" + ], + + "imports": + [ + "io.aklivity.zilla:runtime:${VERSION}", + "io.aklivity.zilla:incubator:${VERSION}" + ], + + "dependencies": + [ + "io.aklivity.zilla:binding-amqp", + "io.aklivity.zilla:binding-echo", + "io.aklivity.zilla:binding-fan", + "io.aklivity.zilla:binding-filesystem", + "io.aklivity.zilla:binding-http", + "io.aklivity.zilla:binding-http-filesystem", + "io.aklivity.zilla:binding-http-kafka", + "io.aklivity.zilla:binding-grpc", + "io.aklivity.zilla:binding-grpc-kafka", + "io.aklivity.zilla:binding-kafka-grpc", + "io.aklivity.zilla:binding-kafka", + "io.aklivity.zilla:binding-mqtt", + "io.aklivity.zilla:binding-mqtt-kafka", + "io.aklivity.zilla:binding-proxy", + "io.aklivity.zilla:binding-sse", + "io.aklivity.zilla:binding-sse-kafka", + "io.aklivity.zilla:binding-tcp", + "io.aklivity.zilla:binding-tls", + "io.aklivity.zilla:binding-ws", + "io.aklivity.zilla:command", + "io.aklivity.zilla:command-config", + "io.aklivity.zilla:command-dump", + "io.aklivity.zilla:command-metrics", + "io.aklivity.zilla:command-start", + "io.aklivity.zilla:command-stop", + "io.aklivity.zilla:command-tune", + "io.aklivity.zilla:engine", + "io.aklivity.zilla:exporter-prometheus", + "io.aklivity.zilla:exporter-otlp", + "io.aklivity.zilla:guard-jwt", + "io.aklivity.zilla:metrics-stream", + "io.aklivity.zilla:metrics-http", + "io.aklivity.zilla:metrics-grpc", + "io.aklivity.zilla:vault-filesystem", + "org.slf4j:slf4j-simple", + "org.antlr:antlr4-runtime" + ] +} diff --git a/cloud/docker-image/src/main/docker/release/Dockerfile b/cloud/docker-image/src/main/docker/release/Dockerfile index 6babc87b1e..78e73cc2dd 100644 --- a/cloud/docker-image/src/main/docker/release/Dockerfile +++ b/cloud/docker-image/src/main/docker/release/Dockerfile @@ -13,12 +13,12 @@ # specific language governing permissions and limitations under the License. # -FROM eclipse-temurin:17-alpine AS build +FROM eclipse-temurin:20-alpine AS build COPY maven /root/.m2/repository COPY zpmw zpmw -COPY zpm.json zpm.json.template +COPY zpm.json.template zpm.json.template RUN apk add --no-cache gettext RUN cat zpm.json.template | env VERSION=${project.version} envsubst > zpm.json @@ -27,7 +27,7 @@ RUN apk add --no-cache wget RUN ./zpmw install --debug --exclude-remote-repositories RUN ./zpmw clean --keep-image -FROM alpine +FROM alpine:3.18.3 COPY --from=build /.zpm /opt/zilla/.zpm COPY --from=build /zilla /opt/zilla/zilla diff --git a/cloud/docker-image/src/main/docker/release/zpm.json b/cloud/docker-image/src/main/docker/release/zpm.json deleted file mode 100644 index 0b2bfaccbd..0000000000 --- a/cloud/docker-image/src/main/docker/release/zpm.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "repositories": - [ - "https://maven.packages.aklivity.io/", - "https://repo.maven.apache.org/maven2/" - ], - - "imports": - [ - "io.aklivity.zilla:runtime:${VERSION}" - ], - - "dependencies": - [ - "io.aklivity.zilla:binding-echo", - "io.aklivity.zilla:binding-fan", - "io.aklivity.zilla:binding-filesystem", - "io.aklivity.zilla:binding-http", - "io.aklivity.zilla:binding-http-filesystem", - "io.aklivity.zilla:binding-http-kafka", - "io.aklivity.zilla:binding-grpc", - "io.aklivity.zilla:binding-grpc-kafka", - "io.aklivity.zilla:binding-kafka-grpc", - "io.aklivity.zilla:binding-kafka", - "io.aklivity.zilla:binding-proxy", - "io.aklivity.zilla:binding-sse", - "io.aklivity.zilla:binding-sse-kafka", - "io.aklivity.zilla:binding-tcp", - "io.aklivity.zilla:binding-tls", - "io.aklivity.zilla:binding-ws", - "io.aklivity.zilla:command", - "io.aklivity.zilla:command-metrics", - "io.aklivity.zilla:command-start", - "io.aklivity.zilla:command-stop", - "io.aklivity.zilla:engine", - "io.aklivity.zilla:exporter-prometheus", - "io.aklivity.zilla:guard-jwt", - "io.aklivity.zilla:metrics-stream", - "io.aklivity.zilla:metrics-http", - "io.aklivity.zilla:metrics-grpc", - "io.aklivity.zilla:vault-filesystem", - "org.slf4j:slf4j-simple", - "org.antlr:antlr4-runtime" - ] -} diff --git a/cloud/docker-image/src/main/docker/release/zpm.json.template b/cloud/docker-image/src/main/docker/release/zpm.json.template new file mode 100644 index 0000000000..8f01f75f91 --- /dev/null +++ b/cloud/docker-image/src/main/docker/release/zpm.json.template @@ -0,0 +1,47 @@ +{ + "repositories": + [ + "https://maven.packages.aklivity.io/", + "https://repo.maven.apache.org/maven2/" + ], + + "imports": + [ + "io.aklivity.zilla:runtime:${VERSION}" + ], + + "dependencies": + [ + "io.aklivity.zilla:binding-echo", + "io.aklivity.zilla:binding-fan", + "io.aklivity.zilla:binding-filesystem", + "io.aklivity.zilla:binding-http", + "io.aklivity.zilla:binding-http-filesystem", + "io.aklivity.zilla:binding-http-kafka", + "io.aklivity.zilla:binding-grpc", + "io.aklivity.zilla:binding-grpc-kafka", + "io.aklivity.zilla:binding-kafka-grpc", + "io.aklivity.zilla:binding-kafka", + "io.aklivity.zilla:binding-mqtt", + "io.aklivity.zilla:binding-mqtt-kafka", + "io.aklivity.zilla:binding-proxy", + "io.aklivity.zilla:binding-sse", + "io.aklivity.zilla:binding-sse-kafka", + "io.aklivity.zilla:binding-tcp", + "io.aklivity.zilla:binding-tls", + "io.aklivity.zilla:binding-ws", + "io.aklivity.zilla:command", + "io.aklivity.zilla:command-metrics", + "io.aklivity.zilla:command-start", + "io.aklivity.zilla:command-stop", + "io.aklivity.zilla:engine", + "io.aklivity.zilla:exporter-prometheus", + "io.aklivity.zilla:guard-jwt", + "io.aklivity.zilla:metrics-stream", + "io.aklivity.zilla:metrics-http", + "io.aklivity.zilla:metrics-grpc", + "io.aklivity.zilla:vault-filesystem", + "org.slf4j:slf4j-simple", + "org.antlr:antlr4-runtime" + ] +} diff --git a/cloud/helm-chart/pom.xml b/cloud/helm-chart/pom.xml index 5a786bb959..e565712d38 100644 --- a/cloud/helm-chart/pom.xml +++ b/cloud/helm-chart/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla cloud - 0.9.51 + 0.9.52 ../pom.xml @@ -51,7 +51,7 @@ io.kokuwa.maven helm-maven-plugin - 6.6.0 + 6.10.0 true src/main/helm diff --git a/cloud/pom.xml b/cloud/pom.xml index 450069bb4c..a704fed85b 100644 --- a/cloud/pom.xml +++ b/cloud/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla zilla - 0.9.51 + 0.9.52 ../pom.xml diff --git a/conf/pom.xml b/conf/pom.xml index 31ee0a4497..2f3f35627d 100644 --- a/conf/pom.xml +++ b/conf/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla zilla - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/binding-amqp.spec/pom.xml b/incubator/binding-amqp.spec/pom.xml index 164d288a09..a84af1ea87 100644 --- a/incubator/binding-amqp.spec/pom.xml +++ b/incubator/binding-amqp.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla incubator - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/binding-amqp/pom.xml b/incubator/binding-amqp/pom.xml index 1afd593469..2a2ef7cc05 100644 --- a/incubator/binding-amqp/pom.xml +++ b/incubator/binding-amqp/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla incubator - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfig.java b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/config/AmqpConditionConfig.java similarity index 94% rename from incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfig.java rename to incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/config/AmqpConditionConfig.java index 22ed7f7782..4571980517 100644 --- a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfig.java +++ b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/config/AmqpConditionConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.amqp.internal.config; +package io.aklivity.zilla.runtime.binding.amqp.config; import io.aklivity.zilla.runtime.binding.amqp.internal.types.AmqpCapabilities; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/AmqpConfiguration.java b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/AmqpConfiguration.java index dc8cb66592..47a5e38fb0 100644 --- a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/AmqpConfiguration.java +++ b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/AmqpConfiguration.java @@ -46,7 +46,7 @@ public class AmqpConfiguration extends Configuration AMQP_INITIAL_DEVIVERY_COUNT = config.property("initial.delivery.count", 0L); AMQP_CLOSE_EXCHANGE_TIMEOUT = config.property("close.exchange.timeout", 10000); AMQP_INCOMING_LOCALES = config.property(String[].class, "incoming.locales", - s -> s.split("\\s+"), c -> AMQP_INCOMING_LOCALES_DEFAULT); + s -> s.split("\\s+"), AMQP_INCOMING_LOCALES_DEFAULT); AMQP_CONFIG = config; } diff --git a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapter.java b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapter.java index f497ee70ee..ffb70b35e3 100644 --- a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapter.java +++ b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.amqp.config.AmqpConditionConfig; import io.aklivity.zilla.runtime.binding.amqp.internal.AmqpBinding; import io.aklivity.zilla.runtime.binding.amqp.internal.types.AmqpCapabilities; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionMatcher.java b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionMatcher.java index 46253cd837..8bc02d652c 100644 --- a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionMatcher.java +++ b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionMatcher.java @@ -18,6 +18,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.amqp.config.AmqpConditionConfig; import io.aklivity.zilla.runtime.binding.amqp.internal.types.AmqpCapabilities; public final class AmqpConditionMatcher diff --git a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpRouteConfig.java b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpRouteConfig.java index b64396f68c..c2041c48e7 100644 --- a/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpRouteConfig.java +++ b/incubator/binding-amqp/src/main/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpRouteConfig.java @@ -20,11 +20,11 @@ import java.util.List; import java.util.function.LongPredicate; +import io.aklivity.zilla.runtime.binding.amqp.config.AmqpConditionConfig; import io.aklivity.zilla.runtime.binding.amqp.internal.types.AmqpCapabilities; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class AmqpRouteConfig extends OptionsConfig +public final class AmqpRouteConfig { public final long id; diff --git a/incubator/binding-amqp/src/main/moditect/module-info.java b/incubator/binding-amqp/src/main/moditect/module-info.java index a4f7f980cb..b89cf580bf 100644 --- a/incubator/binding-amqp/src/main/moditect/module-info.java +++ b/incubator/binding-amqp/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.amqp.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.amqp.internal.AmqpBindingFactorySpi; diff --git a/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapterTest.java b/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapterTest.java index 60884ecbb2..90b509f550 100644 --- a/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapterTest.java +++ b/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/config/AmqpConditionConfigAdapterTest.java @@ -29,6 +29,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.amqp.config.AmqpConditionConfig; + public class AmqpConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AdvisoryIT.java b/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AdvisoryIT.java index f67fc69e9f..c38b02dd34 100644 --- a/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AdvisoryIT.java +++ b/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AdvisoryIT.java @@ -42,9 +42,7 @@ public class AdvisoryIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(2048) - .responseBufferCapacity(2048) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(AMQP_CONTAINER_ID, "server") .configure(ENGINE_DRAIN_ON_CLOSE, false) .configure(AMQP_CLOSE_EXCHANGE_TIMEOUT, 500) diff --git a/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AmqpServerIT.java b/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AmqpServerIT.java index 75eb20bfae..2f3e2218b8 100644 --- a/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AmqpServerIT.java +++ b/incubator/binding-amqp/src/test/java/io/aklivity/zilla/runtime/binding/amqp/internal/stream/server/AmqpServerIT.java @@ -49,9 +49,7 @@ public class AmqpServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(AMQP_CONTAINER_ID, "server") .configure(ENGINE_DRAIN_ON_CLOSE, false) .configure(AMQP_CLOSE_EXCHANGE_TIMEOUT, 500) diff --git a/incubator/binding-mqtt-kafka.spec/NOTICE b/incubator/binding-mqtt-kafka.spec/NOTICE deleted file mode 100644 index 9377db206e..0000000000 --- a/incubator/binding-mqtt-kafka.spec/NOTICE +++ /dev/null @@ -1,21 +0,0 @@ -Licensed under the Aklivity Community License (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - https://www.aklivity.io/aklivity-community-license/ - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -WARRANTIES OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. - -This project includes: - agrona under The Apache License, Version 2.0 - ICU4J under Unicode/ICU License - Jakarta JSON Processing API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception - org.leadpony.justify under The Apache Software License, Version 2.0 - zilla::incubator::binding-mqtt.spec under The Apache Software License, Version 2.0 - zilla::specs::binding-kafka.spec under The Apache Software License, Version 2.0 - zilla::specs::binding-proxy.spec under The Apache Software License, Version 2.0 - zilla::specs::engine.spec under The Apache Software License, Version 2.0 - diff --git a/incubator/binding-mqtt-kafka.spec/pom.xml b/incubator/binding-mqtt-kafka.spec/pom.xml deleted file mode 100644 index ba8f7b56f6..0000000000 --- a/incubator/binding-mqtt-kafka.spec/pom.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - - 4.0.0 - - io.aklivity.zilla - incubator - 0.9.51 - ../pom.xml - - - binding-mqtt-kafka.spec - zilla::incubator::binding-mqtt-kafka.spec - - - - Aklivity Community License Agreement - https://www.aklivity.io/aklivity-community-license/ - repo - - - - - 11 - 11 - 1.00 - 0 - - - - - org.kaazing - k3po.lang - provided - - - ${project.groupId} - engine.spec - ${project.version} - - - ${project.groupId} - binding-mqtt.spec - ${project.version} - - - ${project.groupId} - binding-kafka.spec - ${project.version} - - - junit - junit - test - - - org.kaazing - k3po.junit - test - - - org.hamcrest - hamcrest-library - test - - - - - - - src/main/resources - - - src/main/scripts - - - - - - org.jasig.maven - maven-notice-plugin - - - ${project.groupId} - flyweight-maven-plugin - ${project.version} - - core mqtt kafka - io.aklivity.zilla.specs.binding.mqtt.kafka.internal.types - - - - - validate - generate - - - - - - com.mycila - license-maven-plugin - - - maven-checkstyle-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.moditect - moditect-maven-plugin - - - org.kaazing - k3po-maven-plugin - - - ${project.groupId} - engine - ${project.version} - test-jar - - - ${project.groupId} - engine - ${project.version} - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.jacoco - jacoco-maven-plugin - - - io/aklivity/zilla/specs/binding/mqtt/kafka/internal/types/**/*.class - - - - BUNDLE - - - INSTRUCTION - COVEREDRATIO - ${jacoco.coverage.ratio} - - - CLASS - MISSEDCOUNT - ${jacoco.missed.count} - - - - - - - - - diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json deleted file mode 100644 index e596826c38..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json +++ /dev/null @@ -1,50 +0,0 @@ -[ - { - "op": "add", - "path": "/$defs/binding/properties/type/enum/-", - "value": "mqtt-kafka" - }, - { - "op": "add", - "path": "/$defs/binding/allOf/-", - "value": - { - "if": - { - "properties": - { - "type": - { - "const": "mqtt-kafka" - } - } - }, - "then": - { - "properties": - { - "type": - { - "const": "mqtt-kafka" - }, - "kind": - { - "enum": [ "proxy" ] - }, - "vault": false, - "options": false, - "routes": false - }, - "anyOf": - [ - { - "required": - [ - "exit" - ] - } - ] - } - } - } -] diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/client.rpt deleted file mode 100644 index 03d42cb8c5..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/client.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/server.rpt deleted file mode 100644 index 4e8812f240..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -read aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/client.rpt deleted file mode 100644 index dbfe5cc1e1..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/client.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/server.rpt deleted file mode 100644 index 43a6bb2fe5..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/client.rpt deleted file mode 100644 index 6bb9ec3c76..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/client.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .build() - .build()} - -write zilla:data.empty diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/server.rpt deleted file mode 100644 index 8aedc49335..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .build() - .build()} - -read zilla:data.empty diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/client.rpt deleted file mode 100644 index 8a506a658d..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/client.rpt +++ /dev/null @@ -1,80 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message1" -write flush - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message2" -write flush - - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message3" -write flush - diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/server.rpt deleted file mode 100644 index 75a80dc739..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/server.rpt +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -read "message1" - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -read "message2" - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -read "message3" \ No newline at end of file diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/client.rpt deleted file mode 100644 index b9d3d28ab1..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .headerInt("zilla:timeout-ms", 15000) - .header("zilla:content-type", "message") - .header("zilla:format", "TEXT") - .header("zilla:reply-to", "sensor/one") - .header("zilla:correlation-id", "info") - .build() - .build()} - -write "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/server.rpt deleted file mode 100644 index e598440227..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/server.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .headerInt("zilla:timeout-ms", 15000) - .header("zilla:content-type", "message") - .header("zilla:format", "TEXT") - .header("zilla:reply-to", "sensor/one") - .header("zilla:correlation-id", "info") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/client.rpt deleted file mode 100644 index 85e541a7b4..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/client.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -read aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/server.rpt deleted file mode 100644 index d1655b8bb3..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/client.rpt deleted file mode 100644 index 28f6ca1b52..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/client.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -read zilla:data.empty - -read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/server.rpt deleted file mode 100644 index 8ba85b97fb..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/server.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - -write zilla:data.empty - -write aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt deleted file mode 100644 index d5561c9f80..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -read advised zilla:flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt deleted file mode 100644 index 6b232483f0..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write advise zilla:flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/client.rpt deleted file mode 100644 index d8050b11e2..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/client.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/server.rpt deleted file mode 100644 index ed35626006..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/client.rpt deleted file mode 100644 index a9a56b7bed..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensors/1") - .header("zilla:topic", "sensors") - .header("zilla:topic", "1") - .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") - .header("zilla:format", "TEXT") - .header("row1", "1") - .header("row2", "2") - .build() - .build()} -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/server.rpt deleted file mode 100644 index f822453ebe..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensors/1") - .header("zilla:topic", "sensors") - .header("zilla:topic", "1") - .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") - .header("zilla:format", "TEXT") - .header("row1", "1") - .header("row2", "2") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/client.rpt deleted file mode 100644 index 900025fe31..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensors/1") - .header("zilla:topic", "sensors") - .header("zilla:topic", "1") - .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") - .header("zilla:format", "TEXT") - .header("row1", "1") - .header("row1", "2") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/server.rpt deleted file mode 100644 index 3a5c073c81..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensors/1") - .header("zilla:topic", "sensors") - .header("zilla:topic", "1") - .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") - .header("zilla:format", "TEXT") - .header("row1", "1") - .header("row1", "2") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/client.rpt deleted file mode 100644 index 1b33c42dc8..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensors/1") - .header("zilla:topic", "sensors") - .header("zilla:topic", "1") - .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") - .header("zilla:format", "TEXT") - .header("row", "1") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/server.rpt deleted file mode 100644 index 7dccd60e84..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/server.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensors/1") - .header("zilla:topic", "sensors") - .header("zilla:topic", "1") - .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") - .header("zilla:format", "TEXT") - .header("row", "1") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/client.rpt deleted file mode 100644 index b0f9ea4a60..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/server.rpt deleted file mode 100644 index 53ea0af8be..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/client.rpt deleted file mode 100644 index 554ae22210..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/server.rpt deleted file mode 100644 index fba059b653..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/client.rpt deleted file mode 100644 index 0e6fba6d82..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/server.rpt deleted file mode 100644 index 57b89768d0..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt deleted file mode 100644 index c952290dd9..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .headerInt("zilla:timeout-ms", 15000) - .header("zilla:content-type", "message") - .header("zilla:format", "TEXT") - .header("zilla:reply-to", "sensor/one") - .header("zilla:correlation-id", "info") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt deleted file mode 100644 index 710ae2fb00..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .timestamp(kafka:timestamp()) - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .headerInt("zilla:timeout-ms", 15000) - .header("zilla:content-type", "message") - .header("zilla:format", "TEXT") - .header("zilla:reply-to", "sensor/one") - .header("zilla:correlation-id", "info") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/client.rpt deleted file mode 100644 index 4eb92d03a2..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/client.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .header("row1", "1") - .header("row2", "2") - .header("row2", "3") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/server.rpt deleted file mode 100644 index e9bede539e..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/server.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .timestamp(kafka:timestamp()) - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .header("row1", "1") - .header("row2", "2") - .header("row2", "3") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/client.rpt deleted file mode 100644 index b865d030ac..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/client.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/server.rpt deleted file mode 100644 index ec9540c790..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/server.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .timestamp(kafka:timestamp()) - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/client.rpt deleted file mode 100644 index d1e22a07b8..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/client.rpt +++ /dev/null @@ -1,86 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .headerNot("zilla:local", "client") - .build() - .evaluation("EAGER") - .build() - .build()} -connected - -write notify FIRST_CONNECTED - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client2") - .header("zilla:format", "TEXT") - .build() - .build()} -read "message2" - - -connect await FIRST_CONNECTED - "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/server.rpt deleted file mode 100644 index 21bce7ec08..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/server.rpt +++ /dev/null @@ -1,89 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .headerNot("zilla:local", "client") - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .timestamp(kafka:timestamp()) - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client2") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message2" -write flush - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt_messages") - .partition(-1, -2) - .ackMode("LEADER_ONLY") - .build() - .build()} - - -connected - - - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .deferred(0) - .partition(-1, -1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/client.rpt deleted file mode 100644 index 4751574dcd..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/client.rpt +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write advise zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skipMany() - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .sequence(1) - .build() - .build() - .build() - .build()} - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .filters(3) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one/1") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:topic", "1") - .header("zilla:local", "client2") - .header("zilla:format", "TEXT") - .build() - .build()} - -read "message" \ No newline at end of file diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/server.rpt deleted file mode 100644 index a3bbe5e066..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/server.rpt +++ /dev/null @@ -1,79 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read advised zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skipMany() - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .sequence(1) - .build() - .build() - .build() - .build()} - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .timestamp(kafka:timestamp()) - .filters(3) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one/1") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:topic", "1") - .header("zilla:local", "client2") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/client.rpt deleted file mode 100644 index 2280a88751..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/client.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .build() - .build() - .evaluation("EAGER") - .build() - .build()} -connected - - -read zilla:data.ext ${kafka:matchDataEx() - .typeId(zilla:id("kafka")) - .merged() - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -read "message" \ No newline at end of file diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/server.rpt deleted file mode 100644 index 4b0ddeaf67..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - - -write zilla:data.ext ${kafka:dataEx() - .typeId(zilla:id("kafka")) - .merged() - .timestamp(kafka:timestamp()) - .filters(1) - .partition(0, 1, 2) - .progress(0, 2) - .progress(1, 1) - .key("sensor/one") - .header("zilla:topic", "sensor") - .header("zilla:topic", "one") - .header("zilla:local", "client") - .header("zilla:format", "TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/client.rpt deleted file mode 100644 index b7c2947199..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/server.rpt deleted file mode 100644 index f750ba6e33..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/client.rpt deleted file mode 100644 index 7e23945e68..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read advised zilla:flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/server.rpt deleted file mode 100644 index 769380e04a..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write advise zilla:flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/client.rpt deleted file mode 100644 index aa1cceafcb..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/server.rpt deleted file mode 100644 index 7a0609532c..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/client.rpt deleted file mode 100644 index eb9e9456b6..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/client.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/server.rpt deleted file mode 100644 index 3f731f0f29..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/server.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt deleted file mode 100644 index 5678d76dbd..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .sequence(1) - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt deleted file mode 100644 index 2b497d8eb0..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .sequence(1) - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected \ No newline at end of file diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/client.rpt deleted file mode 100644 index 837a263e35..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/client.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .build() - .build() - .evaluation("EAGER") - .build() - .build()} -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/server.rpt deleted file mode 100644 index 79017a9ae0..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/server.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - - -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/client.rpt deleted file mode 100644 index cfd88f651b..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/client.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skip(1) - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/server.rpt deleted file mode 100644 index 1861b76c4b..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/server.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skip(1) - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/client.rpt deleted file mode 100644 index 71623130fd..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/client.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/server.rpt deleted file mode 100644 index ee7855019f..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - - -connected - - diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt deleted file mode 100644 index ce061a5158..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("device") - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt deleted file mode 100644 index a59d16c0ff..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("device") - .skipMany() - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/client.rpt deleted file mode 100644 index 961aa5b7da..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/client.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - - -connected - -write advise zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .build() - .build()} diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/server.rpt deleted file mode 100644 index a09ec9ad48..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read advised zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .build() - .build()} - diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt deleted file mode 100644 index 39be054da7..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write advise zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("device") - .skipMany() - .build() - .build() - .build() - .build()} diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt deleted file mode 100644 index b9347e2956..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read advised zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("device") - .skipMany() - .build() - .build() - .build() - .build()} diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/client.rpt deleted file mode 100644 index 7d46cfe584..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skipMany() - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .sequence("1") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/server.rpt deleted file mode 100644 index 34778e844f..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .skipMany() - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .skip(1) - .sequence("1") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/client.rpt deleted file mode 100644 index 3f1848188a..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write close -read closed diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/server.rpt deleted file mode 100644 index d5ff77cc79..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/server.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read closed -write close diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/client.rpt deleted file mode 100644 index d5c1573ee4..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/client.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -write advise zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .build() - .build()} diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/server.rpt deleted file mode 100644 index e9a955fe0b..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/server.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:matchBeginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .topic("mqtt_messages") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("one") - .build() - .build() - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .evaluation("EAGER") - .build() - .build()} - -connected - -read advised zilla:flush ${kafka:flushEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("FETCH_ONLY") - .filter() - .headers("zilla:topic") - .sequence("sensor") - .sequence("two") - .build() - .build() - .build() - .build()} diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/client.rpt deleted file mode 100644 index aefebf981a..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} -write zilla:data.empty -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/server.rpt deleted file mode 100644 index 2ab73c22f8..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/server.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/client.rpt deleted file mode 100644 index f6814f1033..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/client.rpt +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -write "message1" -write flush - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -write "message2" -write flush - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -write "message3" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/server.rpt deleted file mode 100644 index bb7207c9b7..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/server.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -read "message1" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -read "message2" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -read "message3" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/client.rpt deleted file mode 100644 index 32e92654da..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -write "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/server.rpt deleted file mode 100644 index 44b70e87bd..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/server.rpt deleted file mode 100644 index 47cd3c75b2..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/server.rpt deleted file mode 100644 index 3144b8ec89..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/server.rpt +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt deleted file mode 100644 index d1f2b4a10b..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write advise zilla:flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/server.rpt deleted file mode 100644 index 971687400a..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/client.rpt deleted file mode 100644 index a822ca4c87..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("sensors/1") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensors/1") - .format("TEXT") - .userProperty("row1", "1") - .userProperty("row2", "2") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/server.rpt deleted file mode 100644 index bdbd6d99bd..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/server.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("sensors/1") - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensors/1") - .format("TEXT") - .userProperty("row1", "1") - .userProperty("row2", "2") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/client.rpt deleted file mode 100644 index 4d2aee3178..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("sensors/1") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensors/1") - .format("TEXT") - .userProperty("row1", "1") - .userProperty("row1", "2") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/server.rpt deleted file mode 100644 index f433deb0ea..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/server.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("sensors/1") - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensors/1") - .format("TEXT") - .userProperty("row1", "1") - .userProperty("row1", "2") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/client.rpt deleted file mode 100644 index 7d068f7ed9..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("sensors/1") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensors/1") - .format("TEXT") - .userProperty("row", "1") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/server.rpt deleted file mode 100644 index d6f0e84f86..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/server.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("sensors/1") - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensors/1") - .format("TEXT") - .userProperty("row", "1") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" - diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/client.rpt deleted file mode 100644 index d5055b5edf..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/client.rpt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/server.rpt deleted file mode 100644 index c9203bad55..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -read aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/client.rpt deleted file mode 100644 index 982a36477f..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/client.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -write zilla:data.empty -write abort \ No newline at end of file diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/server.rpt deleted file mode 100644 index 51f8ee0ecb..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/server.rpt +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -read zilla:data.empty -read aborted \ No newline at end of file diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/client.rpt deleted file mode 100644 index 229c326ab4..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/client.rpt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/server.rpt deleted file mode 100644 index 0579bfee55..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -write aborted diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/client.rpt deleted file mode 100644 index 44776a4901..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -read "message" \ No newline at end of file diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/server.rpt deleted file mode 100644 index 7663c47042..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/server.rpt +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/client.rpt deleted file mode 100644 index 7255e543f2..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/client.rpt +++ /dev/null @@ -1,66 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL", "SEND_RETAINED") - .build() - .build()} - -connected - -write notify SUBSCRIBED - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -read "message2" - - -connect await SUBSCRIBED - "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/server.rpt deleted file mode 100644 index 05531897d5..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/server.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL", "SEND_RETAINED") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -write "message2" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/client.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/client.rpt deleted file mode 100644 index 85e4b4534f..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/client.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/#", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/+/#", 1) - .filter("sensor/+/1", 2) - .build() - .build()} - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one/1") - .subscriptionId(1) - .subscriptionId(2) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/server.rpt b/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/server.rpt deleted file mode 100644 index 0cca50e6eb..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/#", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/+/#", 1) - .filter("sensor/+/1", 2) - .build() - .build()} - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one/1") - .subscriptionId(1) - .subscriptionId(2) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/config/SchemaTest.java b/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/config/SchemaTest.java deleted file mode 100644 index 70e6503724..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/config/SchemaTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.kafka.config; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; - -import jakarta.json.JsonObject; - -import org.junit.Rule; -import org.junit.Test; - -import io.aklivity.zilla.specs.engine.config.ConfigSchemaRule; - -public class SchemaTest -{ - @Rule - public final ConfigSchemaRule schema = new ConfigSchemaRule() - .schemaPatch("io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json") - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config"); - - - @Test - public void shouldValidateProxy() - { - JsonObject config = schema.validate("proxy.yaml"); - - assertThat(config, not(nullValue())); - } -} diff --git a/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java b/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java deleted file mode 100644 index ea3d9100b5..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.kafka.streams; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class KafkaIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("kafka", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${kafka}/publish.client.sent.abort/client", - "${kafka}/publish.client.sent.abort/server"}) - public void shouldPublishReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.client.sent.reset/client", - "${kafka}/publish.client.sent.reset/server"}) - public void shouldPublishReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.server.sent.abort/client", - "${kafka}/publish.server.sent.abort/server"}) - public void shouldPublishReceiveServerSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.server.sent.flush/client", - "${kafka}/publish.server.sent.flush/server"}) - public void shouldPublishReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.server.sent.reset/client", - "${kafka}/publish.server.sent.reset/server"}) - public void shouldPublishReceiveServerSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.server.sent.data/client", - "${kafka}/publish.server.sent.data/server"}) - public void shouldPublishAbortWhenServerSentData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.empty.message/client", - "${kafka}/publish.empty.message/server"}) - public void shouldSendEmptyMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.one.message/client", - "${kafka}/publish.one.message/server"}) - public void shouldSendOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.multiple.messages/client", - "${kafka}/publish.multiple.messages/server"}) - public void shouldSendMultipleMessages() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.with.user.properties.distinct/client", - "${kafka}/publish.with.user.properties.distinct/server"}) - public void shouldSendWithDistinctUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.with.user.properties.repeated/client", - "${kafka}/publish.with.user.properties.repeated/server"}) - public void shouldSendWithRepeatedUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/publish.with.user.property/client", - "${kafka}/publish.with.user.property/server"}) - public void shouldSendWithUserProperty() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.client.sent.abort/client", - "${kafka}/subscribe.client.sent.abort/server"}) - public void shouldSubscribeReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.client.sent.data/client", - "${kafka}/subscribe.client.sent.data/server"}) - public void shouldSubscribeAbortWhenClientSentData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.client.sent.reset/client", - "${kafka}/subscribe.client.sent.reset/server"}) - public void shouldSubscribeReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.server.sent.abort/client", - "${kafka}/subscribe.server.sent.abort/server"}) - public void shouldSubscribeReceiveServerSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.server.sent.flush/client", - "${kafka}/subscribe.server.sent.flush/server"}) - public void shouldSubscribeReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.server.sent.reset/client", - "${kafka}/subscribe.server.sent.reset/server"}) - public void shouldSubscribeReceiveServerSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.one.message/client", - "${kafka}/subscribe.one.message/server"}) - public void shouldReceiveOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.one.message.receive.response.topic.and.correlation.data/client", - "${kafka}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) - public void shouldReceiveCorrelationData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.one.message.user.properties.unaltered/client", - "${kafka}/subscribe.one.message.user.properties.unaltered/server"}) - public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.publish.no.local/client", - "${kafka}/subscribe.publish.no.local/server"}) - public void shouldNotReceiveLocal() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.receive.message.wildcard/client", - "${kafka}/subscribe.receive.message.wildcard/server"}) - public void shouldReceiveOneMessageWithPatternTopic() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.receive.message.overlapping.wildcard/client", - "${kafka}/subscribe.receive.message.overlapping.wildcard/server"}) - public void shouldReceiveMessageOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filter.multi.level.wildcard/client", - "${kafka}/subscribe.topic.filter.multi.level.wildcard/server"}) - public void shouldFilterMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filter.single.level.wildcard/client", - "${kafka}/subscribe.topic.filter.single.level.wildcard/server"}) - public void shouldFilterSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filter.single.and.multi.level.wildcard/client", - "${kafka}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) - public void shouldFilterSingleAndMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filter.two.single.level.wildcard/client", - "${kafka}/subscribe.topic.filter.two.single.level.wildcard/server"}) - public void shouldFilterTwoSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filters.aggregated.both.exact/client", - "${kafka}/subscribe.topic.filters.aggregated.both.exact/server"}) - public void shouldFilterAggregatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filters.isolated.both.exact/client", - "${kafka}/subscribe.topic.filters.isolated.both.exact/server"}) - public void shouldFilterIsolatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filters.overlapping.wildcards/client", - "${kafka}/subscribe.topic.filters.overlapping.wildcards/server"}) - public void shouldFilterOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", - "${kafka}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) - public void shouldFilterAggregatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/subscribe.topic.filters.isolated.exact.and.wildcard/client", - "${kafka}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) - public void shouldFilterIsolatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/unsubscribe.after.subscribe/client", - "${kafka}/unsubscribe.after.subscribe/server"}) - public void shouldAcknowledge() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${kafka}/unsubscribe.topic.filter.single/client", - "${kafka}/unsubscribe.topic.filter.single/server"}) - public void shouldAcknowledgeSingleTopicFilter() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java b/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java deleted file mode 100644 index 9fd5a92980..0000000000 --- a/incubator/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.kafka.streams; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class MqttIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("mqtt", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${mqtt}/publish.client.sent.abort/client", - "${mqtt}/publish.client.sent.abort/server"}) - public void shouldReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.client.sent.reset/client", - "${mqtt}/publish.client.sent.reset/server"}) - public void shouldReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.server.sent.abort/client", - "${mqtt}/publish.server.sent.abort/server"}) - public void shouldPublishReceiveServerSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.server.sent.flush/client", - "${mqtt}/publish.server.sent.flush/server"}) - public void shouldPublishReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.server.sent.reset/client", - "${mqtt}/publish.server.sent.reset/server"}) - public void shouldPublishReceiveServerSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.server.sent.data/client", - "${mqtt}/publish.server.sent.data/server"}) - public void shouldPublishAbortWhenServerSentData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.empty.message/client", - "${mqtt}/publish.empty.message/server"}) - public void shouldSendEmptyMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.one.message/client", - "${mqtt}/publish.one.message/server"}) - public void shouldSendOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.multiple.messages/client", - "${mqtt}/publish.multiple.messages/server"}) - public void shouldSendMultipleMessages() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.with.user.properties.distinct/client", - "${mqtt}/publish.with.user.properties.distinct/server"}) - public void shouldSendWithDistinctUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.with.user.properties.repeated/client", - "${mqtt}/publish.with.user.properties.repeated/server"}) - public void shouldSendWithRepeatedUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/publish.with.user.property/client", - "${mqtt}/publish.with.user.property/server"}) - public void shouldSendWithUserProperty() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.client.sent.abort/client", - "${mqtt}/subscribe.client.sent.abort/server"}) - public void shouldSubscribeReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.client.sent.data/client", - "${mqtt}/subscribe.client.sent.data/server"}) - public void shouldSubscribeAbortWhenClientSentData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.client.sent.reset/client", - "${mqtt}/subscribe.client.sent.reset/server"}) - public void shouldSubscribeReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.server.sent.abort/client", - "${mqtt}/subscribe.server.sent.abort/server"}) - public void shouldSubscribeReceiveServerSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.server.sent.flush/client", - "${mqtt}/subscribe.server.sent.flush/server"}) - public void shouldSubscribeReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.server.sent.reset/client", - "${mqtt}/subscribe.server.sent.reset/server"}) - public void shouldSubscribeReceiveServerSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.one.message/client", - "${mqtt}/subscribe.one.message/server"}) - public void shouldReceiveOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.one.message.receive.response.topic.and.correlation.data/client", - "${mqtt}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) - public void shouldReceiveCorrelationData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.publish.no.local/client", - "${mqtt}/subscribe.publish.no.local/server"}) - public void shouldNotReceiveLocal() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.receive.message.overlapping.wildcard/client", - "${mqtt}/subscribe.receive.message.overlapping.wildcard/server"}) - public void shouldReceiveMessageOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.receive.message.wildcard/client", - "${mqtt}/subscribe.receive.message.wildcard/server"}) - public void shouldReceiveOneMessageWithPatternTopic() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filter.multi.level.wildcard/client", - "${mqtt}/subscribe.topic.filter.multi.level.wildcard/server"}) - public void shouldFilterMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filter.single.level.wildcard/client", - "${mqtt}/subscribe.topic.filter.single.level.wildcard/server"}) - public void shouldFilterSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filter.single.and.multi.level.wildcard/client", - "${mqtt}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) - public void shouldFilterSingleAndMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.one.message.user.properties.unaltered/client", - "${mqtt}/subscribe.one.message.user.properties.unaltered/server"}) - public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filter.two.single.level.wildcard/client", - "${mqtt}/subscribe.topic.filter.two.single.level.wildcard/server"}) - public void shouldFilterTwoSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filters.aggregated.both.exact/client", - "${mqtt}/subscribe.topic.filters.aggregated.both.exact/server"}) - public void shouldFilterAggregatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filters.isolated.both.exact/client", - "${mqtt}/subscribe.topic.filters.isolated.both.exact/server"}) - public void shouldFilterIsolatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filters.overlapping.wildcards/client", - "${mqtt}/subscribe.topic.filters.overlapping.wildcards/server"}) - public void shouldFilterOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", - "${mqtt}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) - public void shouldFilterAggregatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/subscribe.topic.filters.isolated.exact.and.wildcard/client", - "${mqtt}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) - public void shouldFilterIsolatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/unsubscribe.after.subscribe/client", - "${mqtt}/unsubscribe.after.subscribe/server"}) - public void shouldAcknowledge() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${mqtt}/unsubscribe.topic.filter.single/client", - "${mqtt}/unsubscribe.topic.filter.single/server"}) - public void shouldAcknowledgeSingleTopicFilter() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt-kafka/pom.xml b/incubator/binding-mqtt-kafka/pom.xml deleted file mode 100644 index 84554f8413..0000000000 --- a/incubator/binding-mqtt-kafka/pom.xml +++ /dev/null @@ -1,245 +0,0 @@ - - - - 4.0.0 - - io.aklivity.zilla - incubator - 0.9.51 - ../pom.xml - - - binding-mqtt-kafka - zilla::incubator::binding-mqtt-kafka - - - - Aklivity Community License Agreement - https://www.aklivity.io/aklivity-community-license/ - repo - - - - - 11 - 11 - 0.90 - 0 - - - - - ${project.groupId} - binding-mqtt-kafka.spec - ${project.version} - provided - - - ${project.groupId} - engine - ${project.version} - provided - - - ${project.groupId} - engine - test-jar - ${project.version} - test - - - junit - junit - test - - - org.hamcrest - hamcrest - test - - - com.vtence.hamcrest - hamcrest-jpa - test - - - com.github.npathai - hamcrest-optional - test - - - org.mockito - mockito-core - test - - - org.kaazing - k3po.junit - test - - - org.kaazing - k3po.lang - test - - - org.openjdk.jmh - jmh-core - test - - - org.openjdk.jmh - jmh-generator-annprocess - test - - - - - - - org.jasig.maven - maven-notice-plugin - - - ${project.groupId} - flyweight-maven-plugin - ${project.version} - - core mqtt kafka - io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types - - - - - generate - - - - - - com.mycila - license-maven-plugin - - - maven-checkstyle-plugin - - - maven-dependency-plugin - - - process-resources - - unpack - - - - - ${project.groupId} - binding-mqtt-kafka.spec - - - ^\Qio/aklivity/zilla/specs/binding/mqtt/kafka/\E - io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/ - - - - - io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json - ${project.build.directory}/classes - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.moditect - moditect-maven-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - org.kaazing - k3po-maven-plugin - - - ${project.groupId} - engine - ${project.version} - test-jar - - - ${project.groupId} - engine - ${project.version} - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.jacoco - jacoco-maven-plugin - - - io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/types/**/*.class - - - - BUNDLE - - - INSTRUCTION - COVEREDRATIO - ${jacoco.coverage.ratio} - - - CLASS - MISSEDCOUNT - ${jacoco.missed.count} - - - - - - - - io.gatling - maven-shade-plugin - - - - org.agrona:agrona - io.aklivity.zilla:engine - org.openjdk.jmh:jmh-core - net.sf.jopt-simple:jopt-simple - org.apache.commons:commons-math3 - commons-cli:commons-cli - com.github.biboudis:jmh-profilers - - - - - - - diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfiguration.java b/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfiguration.java deleted file mode 100644 index 256e54bdbc..0000000000 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal; - -import io.aklivity.zilla.runtime.engine.Configuration; - -public class MqttKafkaConfiguration extends Configuration -{ - private static final ConfigurationDef MQTT_KAFKA_CONFIG; - - public static final PropertyDef KAFKA_MESSAGES_TOPIC; - - static - { - final ConfigurationDef config = new ConfigurationDef("zilla.binding.mqtt.kafka"); - KAFKA_MESSAGES_TOPIC = config.property("messages.topic", "mqtt_messages"); - MQTT_KAFKA_CONFIG = config; - } - - public MqttKafkaConfiguration( - Configuration config) - { - super(MQTT_KAFKA_CONFIG, config); - } - - public String kafkaMessagesTopic() - { - return KAFKA_MESSAGES_TOPIC.get(this); - } -} diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java b/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java deleted file mode 100644 index 044e5918a5..0000000000 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config; - -import static java.util.stream.Collectors.toList; - -import java.util.List; - -import io.aklivity.zilla.runtime.engine.config.BindingConfig; -import io.aklivity.zilla.runtime.engine.config.KindConfig; - -public class MqttKafkaBindingConfig -{ - public final long id; - public final String entry; - public final KindConfig kind; - public final List routes; - - public MqttKafkaBindingConfig( - BindingConfig binding) - { - this.id = binding.id; - this.entry = binding.entry; - this.kind = binding.kind; - this.routes = binding.routes.stream().map(MqttKafkaRouteConfig::new).collect(toList()); - } - - public MqttKafkaRouteConfig resolve( - long authorization) - { - return routes.stream() - .filter(r -> r.authorized(authorization)) - .findFirst() - .orElse(null); - } -} diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java b/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java deleted file mode 100644 index 665433e21e..0000000000 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java +++ /dev/null @@ -1,1159 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; - -import static java.time.Instant.now; - -import java.nio.ByteOrder; -import java.util.function.LongFunction; -import java.util.function.LongUnaryOperator; - -import org.agrona.DirectBuffer; -import org.agrona.MutableDirectBuffer; -import org.agrona.concurrent.UnsafeBuffer; - -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaHeaderHelper; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaRouteConfig; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Flyweight; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaAckMode; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaCapabilities; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaHeaderFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaKeyFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormatFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.AbortFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.BeginFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.DataFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.EndFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ExtensionFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.FlushFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaBeginExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaDataExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttPublishBeginExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttPublishDataExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ResetFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.WindowFW; -import io.aklivity.zilla.runtime.engine.EngineContext; -import io.aklivity.zilla.runtime.engine.binding.BindingHandler; -import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; -import io.aklivity.zilla.runtime.engine.concurrent.Signaler; - -public class MqttKafkaPublishFactory implements BindingHandler -{ - //TODO: these defaults should come from the binding config - private static final String KAFKA_MESSAGES_TOPIC_NAME = "mqtt_messages"; - private static final KafkaAckMode KAFKA_DEFAULT_ACK_MODE = KafkaAckMode.LEADER_ONLY; - private static final String MQTT_TYPE_NAME = "mqtt"; - private static final String KAFKA_TYPE_NAME = "kafka"; - - private final OctetsFW emptyRO = new OctetsFW().wrap(new UnsafeBuffer(0L, 0), 0, 0); - private final BeginFW beginRO = new BeginFW(); - private final DataFW dataRO = new DataFW(); - private final EndFW endRO = new EndFW(); - private final AbortFW abortRO = new AbortFW(); - private final FlushFW flushRO = new FlushFW(); - - private final BeginFW.Builder beginRW = new BeginFW.Builder(); - private final DataFW.Builder dataRW = new DataFW.Builder(); - private final EndFW.Builder endRW = new EndFW.Builder(); - private final AbortFW.Builder abortRW = new AbortFW.Builder(); - private final FlushFW.Builder flushRW = new FlushFW.Builder(); - - private final WindowFW windowRO = new WindowFW(); - private final ResetFW resetRO = new ResetFW(); - - private final WindowFW.Builder windowRW = new WindowFW.Builder(); - private final ResetFW.Builder resetRW = new ResetFW.Builder(); - - private final ExtensionFW extensionRO = new ExtensionFW(); - private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); - private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); - private final KafkaDataExFW kafkaDataExRO = new KafkaDataExFW(); - - private final MqttDataExFW.Builder mqttDataExRW = new MqttDataExFW.Builder(); - - private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); - private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); - private final Array32FW.Builder kafkaHeadersRW = - new Array32FW.Builder<>(new KafkaHeaderFW.Builder(), new KafkaHeaderFW()); - private final MutableDirectBuffer writeBuffer; - private final MutableDirectBuffer keyBuffer; - private final MutableDirectBuffer headerIntValueBuffer; - private final MutableDirectBuffer extBuffer; - private final MutableDirectBuffer kafkaHeadersBuffer; - private final BindingHandler streamFactory; - private final LongUnaryOperator supplyInitialId; - private final LongUnaryOperator supplyReplyId; - private final MqttKafkaHeaderHelper helper; - private final int mqttTypeId; - private final int kafkaTypeId; - private final Signaler signaler; - private final LongFunction supplyBinding; - private KafkaKeyFW key; - - private OctetsFW[] topicNameHeaders; - private OctetsFW clientIdOctets; - private String16FW binaryFormat; - private String16FW textFormat; - - public MqttKafkaPublishFactory( - MqttKafkaConfiguration config, - EngineContext context, - LongFunction supplyBinding) - { - this.mqttTypeId = context.supplyTypeId(MQTT_TYPE_NAME); - this.kafkaTypeId = context.supplyTypeId(KAFKA_TYPE_NAME); - this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); - this.keyBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); - this.headerIntValueBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); - this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); - this.kafkaHeadersBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); - this.helper = new MqttKafkaHeaderHelper(); - this.signaler = context.signaler(); - this.streamFactory = context.streamFactory(); - this.supplyInitialId = context::supplyInitialId; - this.supplyReplyId = context::supplyReplyId; - this.supplyBinding = supplyBinding; - this.binaryFormat = new String16FW(MqttPayloadFormat.BINARY.name()); - this.textFormat = new String16FW(MqttPayloadFormat.TEXT.name()); - } - - @Override - public MessageConsumer newStream( - int msgTypeId, - DirectBuffer buffer, - int index, - int length, - MessageConsumer mqtt) - { - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - final long originId = begin.originId(); - final long routedId = begin.routedId(); - final long initialId = begin.streamId(); - final long authorization = begin.authorization(); - - final OctetsFW extension = begin.extension(); - final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); - - assert mqttBeginEx.kind() == MqttBeginExFW.KIND_PUBLISH; - final MqttPublishBeginExFW mqttPublishBeginEx = mqttBeginEx.publish(); - String topicName = mqttPublishBeginEx.topic().asString(); - assert topicName != null; - - String[] topicHeaders = topicName.split("/"); - topicNameHeaders = new OctetsFW[topicHeaders.length]; - for (int i = 0; i < topicHeaders.length; i++) - { - String16FW topicHeader = new String16FW(topicHeaders[i]); - topicNameHeaders[i] = new OctetsFW().wrap(topicHeader.value(), 0, topicHeader.length()); - } - clientIdOctets = new OctetsFW() - .wrap(mqttPublishBeginEx.clientId().value(), 0, mqttPublishBeginEx.clientId().length()); - final DirectBuffer topicNameBuffer = mqttPublishBeginEx.topic().value(); - key = new KafkaKeyFW.Builder() - .wrap(keyBuffer, 0, keyBuffer.capacity()) - .length(topicNameBuffer.capacity()) - .value(topicNameBuffer, 0, topicNameBuffer.capacity()) - .build(); - - final MqttKafkaBindingConfig binding = supplyBinding.apply(routedId); - - final MqttKafkaRouteConfig resolved = binding != null ? binding.resolve(authorization) : null; - - - MessageConsumer newStream = null; - - if (resolved != null) - { - final long resolvedId = resolved.id; - newStream = new MqttPublishProxy(mqtt, originId, routedId, initialId, resolvedId)::onMqttMessage; - } - - return newStream; - } - - private final class MqttPublishProxy - { - private final MessageConsumer mqtt; - private final long originId; - private final long routedId; - private final long initialId; - private final long replyId; - private final KafkaProxy delegate; - - private int state; - - private long initialSeq; - private long initialAck; - private int initialMax; - - private long replySeq; - private long replyAck; - private int replyMax; - private int replyPad; - - private MqttPublishProxy( - MessageConsumer mqtt, - long originId, - long routedId, - long initialId, - long resolvedId) - { - this.mqtt = mqtt; - this.originId = originId; - this.routedId = routedId; - this.initialId = initialId; - this.replyId = supplyReplyId.applyAsLong(initialId); - this.delegate = new KafkaProxy(originId, resolvedId, this); - } - - private void onMqttMessage( - int msgTypeId, - DirectBuffer buffer, - int index, - int length) - { - switch (msgTypeId) - { - case BeginFW.TYPE_ID: - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - onMqttBegin(begin); - break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onMqttData(data); - break; - case EndFW.TYPE_ID: - final EndFW end = endRO.wrap(buffer, index, index + length); - onMqttEnd(end); - break; - case AbortFW.TYPE_ID: - final AbortFW abort = abortRO.wrap(buffer, index, index + length); - onMqttAbort(abort); - break; - case ResetFW.TYPE_ID: - final ResetFW reset = resetRO.wrap(buffer, index, index + length); - onMqttReset(reset); - break; - case WindowFW.TYPE_ID: - final WindowFW window = windowRO.wrap(buffer, index, index + length); - onMqttWindow(window); - break; - } - } - - private void onMqttBegin( - BeginFW begin) - { - final long sequence = begin.sequence(); - final long acknowledge = begin.acknowledge(); - final long traceId = begin.traceId(); - final long authorization = begin.authorization(); - final long affinity = begin.affinity(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - assert acknowledge >= initialAck; - - initialSeq = sequence; - initialAck = acknowledge; - state = MqttKafkaState.openingInitial(state); - - assert initialAck <= initialSeq; - - delegate.doKafkaBegin(traceId, authorization, affinity); - } - - private void onMqttData( - DataFW data) - { - final long sequence = data.sequence(); - final long acknowledge = data.acknowledge(); - final long traceId = data.traceId(); - final long authorization = data.authorization(); - final long budgetId = data.budgetId(); - final int reserved = data.reserved(); - final int flags = data.flags(); - final OctetsFW payload = data.payload(); - final OctetsFW extension = data.extension(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - - initialSeq = sequence; - - assert initialAck <= initialSeq; - - Flyweight kafkaDataEx = emptyRO; - MqttDataExFW mqttDataEx = null; - if (extension.sizeof() > 0) - { - mqttDataEx = extension.get(mqttDataExRO::tryWrap); - } - - assert mqttDataEx.kind() == MqttDataExFW.KIND_PUBLISH; - final MqttPublishDataExFW mqttPublishDataEx = mqttDataEx.publish(); - kafkaHeadersRW.wrap(kafkaHeadersBuffer, 0, kafkaHeadersBuffer.capacity()); - - for (OctetsFW topicHeader : topicNameHeaders) - { - addHeader(helper.kafkaTopicHeaderName, topicHeader); - } - - addHeader(helper.kafkaLocalHeaderName, clientIdOctets); - - if (mqttPublishDataEx.expiryInterval() != -1) - { - addHeader(helper.kafkaTimeoutHeaderName, mqttPublishDataEx.expiryInterval() * 1000); - } - - if (mqttPublishDataEx.contentType().asString() != null) - { - addHeader(helper.kafkaContentTypeHeaderName, mqttPublishDataEx.contentType()); - } - - if (payload.sizeof() != 0 && mqttPublishDataEx.format() != null) - { - addHeader(helper.kafkaFormatHeaderName, mqttPublishDataEx.format()); - } - - if (mqttPublishDataEx.responseTopic().asString() != null) - { - addHeader(helper.kafkaReplyToHeaderName, mqttPublishDataEx.responseTopic()); - } - - if (mqttPublishDataEx.correlation().bytes() != null) - { - addHeader(helper.kafkaCorrelationHeaderName, mqttPublishDataEx.correlation().bytes()); - } - - mqttPublishDataEx.properties().forEach(property -> - addHeader(property.key(), property.value())); - - final int deferred = mqttPublishDataEx.deferred(); - kafkaDataEx = kafkaDataExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m - .deferred(deferred) - .timestamp(now().toEpochMilli()) - .partition(p -> p.partitionId(-1).partitionOffset(-1)) - .key(b -> b.set(key)) - .headers(kafkaHeadersRW.build())) - .build(); - - //TODO: do this onMqttData for subscribe - // doMqttReset(traceId); - // delegate.doKafkaAbort(traceId, authorization); - delegate.doKafkaData(traceId, authorization, budgetId, reserved, flags, payload, kafkaDataEx); - } - - - private void onMqttEnd( - EndFW end) - { - final long sequence = end.sequence(); - final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - - initialSeq = sequence; - state = MqttKafkaState.closeInitial(state); - - assert initialAck <= initialSeq; - - delegate.doKafkaEnd(traceId, initialSeq, authorization); - } - - private void onMqttAbort( - AbortFW abort) - { - final long sequence = abort.sequence(); - final long acknowledge = abort.acknowledge(); - final long traceId = abort.traceId(); - final long authorization = abort.authorization(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - - initialSeq = sequence; - state = MqttKafkaState.closeInitial(state); - - assert initialAck <= initialSeq; - - delegate.doKafkaAbort(traceId, authorization); - } - - private void onMqttReset( - ResetFW reset) - { - final long sequence = reset.sequence(); - final long acknowledge = reset.acknowledge(); - final int maximum = reset.maximum(); - final long traceId = reset.traceId(); - - assert acknowledge <= sequence; - assert sequence <= replySeq; - assert acknowledge >= replyAck; - assert maximum >= replyMax; - - replyAck = acknowledge; - replyMax = maximum; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - delegate.doKafkaReset(traceId); - } - - private void onMqttWindow( - WindowFW window) - { - final long sequence = window.sequence(); - final long acknowledge = window.acknowledge(); - final int maximum = window.maximum(); - final long traceId = window.traceId(); - final long authorization = window.authorization(); - final long budgetId = window.budgetId(); - final int padding = window.padding(); - final int capabilities = window.capabilities(); - - assert acknowledge <= sequence; - assert sequence <= replySeq; - assert acknowledge >= replyAck; - assert maximum >= replyMax; - - replyAck = acknowledge; - replyMax = maximum; - replyPad = padding; - state = MqttKafkaState.openReply(state); - - assert replyAck <= replySeq; - - delegate.doKafkaWindow(traceId, authorization, budgetId, padding, capabilities); - } - - private void doMqttBegin( - long traceId, - long authorization, - long affinity) - { - replySeq = delegate.replySeq; - replyAck = delegate.replyAck; - replyMax = delegate.replyMax; - state = MqttKafkaState.openingReply(state); - - doBegin(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, affinity); - } - - private void doMqttData( - long traceId, - long authorization, - long budgetId, - int reserved, - int flags, - OctetsFW payload, - Flyweight extension) - { - doData(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); - - replySeq += reserved; - - assert replySeq <= replyAck + replyMax; - } - - private void doMqttFlush( - long traceId, - long authorization, - long budgetId, - int reserved) - { - replySeq = delegate.replySeq; - - doFlush(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization, budgetId, reserved); - } - - private void doMqttAbort( - long traceId, - long authorization) - { - if (!MqttKafkaState.replyClosed(state)) - { - replySeq = delegate.replySeq; - state = MqttKafkaState.closeReply(state); - - doAbort(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); - } - } - - private void doMqttEnd( - long traceId, - long authorization) - { - if (!MqttKafkaState.replyClosed(state)) - { - replySeq = delegate.replySeq; - state = MqttKafkaState.closeReply(state); - - doEnd(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); - } - } - - private void doMqttWindow( - long authorization, - long traceId, - long budgetId, - int padding, - int capabilities) - { - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - - doWindow(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, padding, 0, capabilities); - } - - private void doMqttReset( - long traceId) - { - if (!MqttKafkaState.initialClosed(state)) - { - state = MqttKafkaState.closeInitial(state); - - doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId); - } - } - } - - private void addHeader( - OctetsFW key, - int value) - { - headerIntValueBuffer.putInt(0, value, ByteOrder.BIG_ENDIAN); - kafkaHeadersRW.item(h -> - { - h.nameLen(key.sizeof()); - h.name(key); - h.valueLen(4); - h.value(headerIntValueBuffer, 0, 4); - }); - } - - private void addHeader( - OctetsFW key, - OctetsFW value) - { - kafkaHeadersRW.item(h -> - { - h.nameLen(key.sizeof()); - h.name(key); - h.valueLen(value.sizeof()); - h.value(value); - }); - } - - private void addHeader( - OctetsFW key, - MqttPayloadFormatFW format) - { - String16FW value = format.get() == MqttPayloadFormat.BINARY ? binaryFormat : textFormat; - addHeader(key, value); - } - - private void addHeader( - OctetsFW key, - String16FW value) - { - DirectBuffer buffer = value.value(); - kafkaHeadersRW.item(h -> - { - h.nameLen(key.sizeof()); - h.name(key); - h.valueLen(value.length()); - h.value(buffer, 0, buffer.capacity()); - }); - } - - private void addHeader(String16FW key, String16FW value) - { - DirectBuffer keyBuffer = key.value(); - DirectBuffer valueBuffer = value.value(); - kafkaHeadersRW.item(h -> - { - h.nameLen(key.length()); - h.name(keyBuffer, 0, keyBuffer.capacity()); - h.valueLen(value.length()); - h.value(valueBuffer, 0, valueBuffer.capacity()); - }); - } - - - final class KafkaProxy - { - private MessageConsumer kafka; - private final long originId; - private final long routedId; - private final long initialId; - private final long replyId; - private final MqttPublishProxy delegate; - - private int state; - - private long initialSeq; - private long initialAck; - private int initialMax; - - private long replySeq; - private long replyAck; - private int replyMax; - private int replyPad; - - private KafkaProxy( - long originId, - long routedId, - MqttPublishProxy delegate) - { - this.originId = originId; - this.routedId = routedId; - this.delegate = delegate; - this.initialId = supplyInitialId.applyAsLong(routedId); - this.replyId = supplyReplyId.applyAsLong(initialId); - } - - private void doKafkaBegin( - long traceId, - long authorization, - long affinity) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.openingInitial(state); - - kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity); - } - - private void doKafkaData( - long traceId, - long authorization, - long budgetId, - int reserved, - int flags, - OctetsFW payload, - Flyweight extension) - { - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); - - initialSeq += reserved; - - assert initialSeq <= initialAck + initialMax; - } - - private void doKafkaEnd( - long traceId, - long sequence, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void doKafkaAbort( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void onKafkaMessage( - int msgTypeId, - DirectBuffer buffer, - int index, - int length) - { - switch (msgTypeId) - { - case BeginFW.TYPE_ID: - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - onKafkaBegin(begin); - break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onKafkaData(data); - break; - case EndFW.TYPE_ID: - final EndFW end = endRO.wrap(buffer, index, index + length); - onKafkaEnd(end); - break; - case AbortFW.TYPE_ID: - final AbortFW abort = abortRO.wrap(buffer, index, index + length); - onKafkaAbort(abort); - break; - case FlushFW.TYPE_ID: - final FlushFW flush = flushRO.wrap(buffer, index, index + length); - onKafkaFlush(flush); - break; - case WindowFW.TYPE_ID: - final WindowFW window = windowRO.wrap(buffer, index, index + length); - onKafkaWindow(window); - break; - case ResetFW.TYPE_ID: - final ResetFW reset = resetRO.wrap(buffer, index, index + length); - onKafkaReset(reset); - break; - } - } - - private void onKafkaBegin( - BeginFW begin) - { - final long sequence = begin.sequence(); - final long acknowledge = begin.acknowledge(); - final int maximum = begin.maximum(); - final long traceId = begin.traceId(); - final long authorization = begin.authorization(); - final long affinity = begin.affinity(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - assert acknowledge >= replyAck; - - replySeq = sequence; - replyAck = acknowledge; - replyMax = maximum; - state = MqttKafkaState.openingReply(state); - - assert replyAck <= replySeq; - - delegate.doMqttBegin(traceId, authorization, affinity); - } - - private void onKafkaData( - DataFW data) - { - final long sequence = data.sequence(); - final long acknowledge = data.acknowledge(); - final long traceId = data.traceId(); - final long authorization = data.authorization(); - final long budgetId = data.budgetId(); - final int reserved = data.reserved(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence + reserved; - - assert replyAck <= replySeq; - doKafkaReset(traceId); - delegate.doMqttAbort(traceId, authorization); - } - - private void onKafkaEnd( - EndFW end) - { - final long sequence = end.sequence(); - final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - delegate.doMqttEnd(traceId, authorization); - } - - private void onKafkaFlush( - FlushFW flush) - { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - final long budgetId = flush.budgetId(); - final int reserved = flush.reserved(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - - assert replyAck <= replySeq; - - delegate.doMqttFlush(traceId, authorization, budgetId, reserved); - } - - private void onKafkaAbort( - AbortFW abort) - { - final long sequence = abort.sequence(); - final long acknowledge = abort.acknowledge(); - final long traceId = abort.traceId(); - final long authorization = abort.authorization(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - delegate.doMqttAbort(traceId, authorization); - } - - private void onKafkaWindow( - WindowFW window) - { - final long sequence = window.sequence(); - final long acknowledge = window.acknowledge(); - final int maximum = window.maximum(); - final long authorization = window.authorization(); - final long traceId = window.traceId(); - final long budgetId = window.budgetId(); - final int padding = window.padding(); - final int capabilities = window.capabilities(); - - assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; - assert maximum >= delegate.initialMax; - - initialAck = acknowledge; - initialMax = maximum; - state = MqttKafkaState.openInitial(state); - - assert initialAck <= initialSeq; - - delegate.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); - } - - private void onKafkaReset( - ResetFW reset) - { - final long sequence = reset.sequence(); - final long acknowledge = reset.acknowledge(); - final long traceId = reset.traceId(); - - assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; - - delegate.initialAck = acknowledge; - - assert delegate.initialAck <= delegate.initialSeq; - - delegate.doMqttReset(traceId); - } - - private void doKafkaReset( - long traceId) - { - if (!MqttKafkaState.replyClosed(state)) - { - state = MqttKafkaState.closeReply(state); - - doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId); - } - } - - private void doKafkaWindow( - long traceId, - long authorization, - long budgetId, - int padding, - int capabilities) - { - replyAck = delegate.replyAck; - replyMax = delegate.replyMax; - replyPad = delegate.replyPad; - - doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, padding, replyPad, capabilities); - } - } - - - private void doBegin( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long affinity) - { - final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .affinity(affinity) - .build(); - - receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); - } - - private void doData( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long budgetId, - int flags, - int reserved, - OctetsFW payload, - Flyweight extension) - { - final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .flags(flags) - .budgetId(budgetId) - .reserved(reserved) - .payload(payload) - .extension(extension.buffer(), extension.offset(), extension.sizeof()) - .build(); - - receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); - } - - private void doEnd( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization) - { - final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .build(); - - receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); - } - - private void doAbort( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization) - { - final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .build(); - - receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); - } - - private void doFlush( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long budgetId, - int reserved) - { - final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .budgetId(budgetId) - .reserved(reserved) - .build(); - - receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); - } - - private MessageConsumer newKafkaStream( - MessageConsumer sender, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long affinity) - { - final KafkaBeginExFW kafkaBeginEx = - kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.capabilities(c -> c.set(KafkaCapabilities.PRODUCE_ONLY)) - .topic(KAFKA_MESSAGES_TOPIC_NAME) - .partitionsItem(p -> p.partitionId(-1).partitionOffset(-2L)) - .ackMode(b -> b.set(KAFKA_DEFAULT_ACK_MODE))) - .build(); - - - final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .affinity(affinity) - .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) - .build(); - - MessageConsumer receiver = - streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); - - receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); - - return receiver; - } - - private void doWindow( - MessageConsumer sender, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long budgetId, - int padding, - int minimum, - int capabilities) - { - final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .budgetId(budgetId) - .padding(padding) - .minimum(minimum) - .capabilities(capabilities) - .build(); - - sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); - } - - private void doReset( - MessageConsumer sender, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId) - { - final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .build(); - - sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); - } -} diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java b/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java deleted file mode 100644 index 8e68a70bd1..0000000000 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java +++ /dev/null @@ -1,1212 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; - - -import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSubscribeFlags.NO_LOCAL; - -import java.util.function.LongFunction; -import java.util.function.LongUnaryOperator; - -import org.agrona.DirectBuffer; -import org.agrona.MutableDirectBuffer; -import org.agrona.collections.IntArrayList; -import org.agrona.concurrent.UnsafeBuffer; - -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaHeaderHelper; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaRouteConfig; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Flyweight; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaCapabilities; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaConditionFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaEvaluation; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaHeaderFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaOffsetFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaSkip; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttTopicFilterFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.AbortFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.BeginFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.DataFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.EndFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ExtensionFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.FlushFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaBeginExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaDataExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaFlushExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedDataExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttFlushExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSubscribeBeginExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSubscribeFlushExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ResetFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.WindowFW; -import io.aklivity.zilla.runtime.engine.EngineContext; -import io.aklivity.zilla.runtime.engine.binding.BindingHandler; -import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; -import io.aklivity.zilla.runtime.engine.concurrent.Signaler; - -public class MqttKafkaSubscribeFactory implements BindingHandler -{ - private static final String MQTT_TYPE_NAME = "mqtt"; - private static final String KAFKA_TYPE_NAME = "kafka"; - private static final String MQTT_SINGLE_LEVEL_WILDCARD = "+"; - private static final String MQTT_MULTI_LEVEL_WILDCARD = "#"; - private static final int NO_LOCAL_FLAG = 1 << NO_LOCAL.ordinal(); - - private final OctetsFW emptyRO = new OctetsFW().wrap(new UnsafeBuffer(0L, 0), 0, 0); - private final BeginFW beginRO = new BeginFW(); - private final DataFW dataRO = new DataFW(); - private final EndFW endRO = new EndFW(); - private final AbortFW abortRO = new AbortFW(); - private final FlushFW flushRO = new FlushFW(); - - private final BeginFW.Builder beginRW = new BeginFW.Builder(); - private final DataFW.Builder dataRW = new DataFW.Builder(); - private final EndFW.Builder endRW = new EndFW.Builder(); - private final AbortFW.Builder abortRW = new AbortFW.Builder(); - private final FlushFW.Builder flushRW = new FlushFW.Builder(); - private final OctetsFW.Builder octetsRW = new OctetsFW.Builder(); - - private final WindowFW windowRO = new WindowFW(); - private final ResetFW resetRO = new ResetFW(); - - private final WindowFW.Builder windowRW = new WindowFW.Builder(); - private final ResetFW.Builder resetRW = new ResetFW.Builder(); - - private final ExtensionFW extensionRO = new ExtensionFW(); - private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); - private final MqttFlushExFW mqttFlushExRO = new MqttFlushExFW(); - private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); - private final KafkaDataExFW kafkaDataExRO = new KafkaDataExFW(); - private final KafkaHeaderFW kafkaHeaderRO = new KafkaHeaderFW(); - - private final MqttDataExFW.Builder mqttDataExRW = new MqttDataExFW.Builder(); - - private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); - private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); - - private final MutableDirectBuffer writeBuffer; - private final MutableDirectBuffer extBuffer; - private final BindingHandler streamFactory; - private final LongUnaryOperator supplyInitialId; - private final LongUnaryOperator supplyReplyId; - private final int mqttTypeId; - private final int kafkaTypeId; - private final Signaler signaler; - private final LongFunction supplyBinding; - private final MqttKafkaHeaderHelper helper; - - private String clientId; - private Array32FW filters; - private IntArrayList subscriptionIds = new IntArrayList(); - private String16FW kafkaMessagesTopicName; - - public MqttKafkaSubscribeFactory( - MqttKafkaConfiguration config, - EngineContext context, - LongFunction supplyBinding) - { - this.mqttTypeId = context.supplyTypeId(MQTT_TYPE_NAME); - this.kafkaTypeId = context.supplyTypeId(KAFKA_TYPE_NAME); - this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); - this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); - this.signaler = context.signaler(); - this.streamFactory = context.streamFactory(); - this.supplyInitialId = context::supplyInitialId; - this.supplyReplyId = context::supplyReplyId; - this.supplyBinding = supplyBinding; - this.helper = new MqttKafkaHeaderHelper(); - this.kafkaMessagesTopicName = new String16FW(config.kafkaMessagesTopic()); - } - - @Override - public MessageConsumer newStream( - int msgTypeId, - DirectBuffer buffer, - int index, - int length, - MessageConsumer mqtt) - { - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - final long originId = begin.originId(); - final long routedId = begin.routedId(); - final long initialId = begin.streamId(); - final long authorization = begin.authorization(); - - final OctetsFW extension = begin.extension(); - final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); - - assert mqttBeginEx.kind() == MqttBeginExFW.KIND_SUBSCRIBE; - final MqttSubscribeBeginExFW mqttSubscribeBeginEx = mqttBeginEx.subscribe(); - clientId = mqttSubscribeBeginEx.clientId().asString(); - filters = mqttSubscribeBeginEx.filters(); - - final MqttKafkaBindingConfig binding = supplyBinding.apply(routedId); - - final MqttKafkaRouteConfig resolved = binding != null ? binding.resolve(authorization) : null; - - - MessageConsumer newStream = null; - - if (resolved != null) - { - final long resolvedId = resolved.id; - newStream = new MqttSubscribeProxy(mqtt, originId, routedId, initialId, resolvedId)::onMqttMessage; - } - - return newStream; - } - - private final class MqttSubscribeProxy - { - private final MessageConsumer mqtt; - private final long originId; - private final long routedId; - private final long initialId; - private final long replyId; - private final KafkaProxy delegate; - - private int state; - - private long initialSeq; - private long initialAck; - private int initialMax; - - private long replySeq; - private long replyAck; - private int replyMax; - private int replyPad; - - private MqttSubscribeProxy( - MessageConsumer mqtt, - long originId, - long routedId, - long initialId, - long resolvedId) - { - this.mqtt = mqtt; - this.originId = originId; - this.routedId = routedId; - this.initialId = initialId; - this.replyId = supplyReplyId.applyAsLong(initialId); - this.delegate = new KafkaProxy(originId, resolvedId, this); - } - - private void onMqttMessage( - int msgTypeId, - DirectBuffer buffer, - int index, - int length) - { - switch (msgTypeId) - { - case BeginFW.TYPE_ID: - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - onMqttBegin(begin); - break; - case FlushFW.TYPE_ID: - final FlushFW flush = flushRO.wrap(buffer, index, index + length); - onMqttFlush(flush); - break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onMqttData(data); - break; - case EndFW.TYPE_ID: - final EndFW end = endRO.wrap(buffer, index, index + length); - onMqttEnd(end); - break; - case AbortFW.TYPE_ID: - final AbortFW abort = abortRO.wrap(buffer, index, index + length); - onMqttAbort(abort); - break; - case ResetFW.TYPE_ID: - final ResetFW reset = resetRO.wrap(buffer, index, index + length); - onMqttReset(reset); - break; - case WindowFW.TYPE_ID: - final WindowFW window = windowRO.wrap(buffer, index, index + length); - onMqttWindow(window); - break; - } - } - - private void onMqttBegin( - BeginFW begin) - { - final long sequence = begin.sequence(); - final long acknowledge = begin.acknowledge(); - final long traceId = begin.traceId(); - final long authorization = begin.authorization(); - final long affinity = begin.affinity(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - assert acknowledge >= initialAck; - - initialSeq = sequence; - initialAck = acknowledge; - state = MqttKafkaState.openingInitial(state); - - assert initialAck <= initialSeq; - - delegate.doKafkaBegin(traceId, authorization, affinity); - } - - private void onMqttFlush( - FlushFW flush) - { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - final long budgetId = flush.budgetId(); - final int reserved = flush.reserved(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - - assert replyAck <= replySeq; - - final OctetsFW extension = flush.extension(); - final MqttFlushExFW mqttFlushEx = extension.get(mqttFlushExRO::tryWrap); - - assert mqttFlushEx.kind() == MqttFlushExFW.KIND_SUBSCRIBE; - final MqttSubscribeFlushExFW mqttSubscribeFlushEx = mqttFlushEx.subscribe(); - - filters = mqttSubscribeFlushEx.filters(); - subscriptionIds.clear(); - - - final KafkaFlushExFW kafkaFlushEx = - kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> - { - m.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); - filters.forEach(filter -> - - m.filtersItem(f -> - { - f.conditionsItem(ci -> - { - subscriptionIds.add((int) filter.subscriptionId()); - buildHeaders(ci, filter.pattern().asString()); - }); - boolean noLocal = (filter.flags() & NO_LOCAL_FLAG) != 0; - if (noLocal) - { - final DirectBuffer valueBuffer = new String16FW(clientId).value(); - f.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> - h.nameLen(helper.kafkaLocalHeaderName.sizeof()) - .name(helper.kafkaLocalHeaderName) - .valueLen(valueBuffer.capacity()) - .value(valueBuffer, 0, valueBuffer.capacity()))))); - } - })); - }) - .build(); - - delegate.doKafkaFlush(traceId, authorization, budgetId, reserved, kafkaFlushEx); - } - - private void onMqttData( - DataFW data) - { - final long sequence = data.sequence(); - final long acknowledge = data.acknowledge(); - final long traceId = data.traceId(); - final long authorization = data.authorization(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - - initialSeq = sequence; - - assert initialAck <= initialSeq; - - doMqttReset(traceId); - delegate.doKafkaAbort(traceId, authorization); - } - - - private void onMqttEnd( - EndFW end) - { - final long sequence = end.sequence(); - final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - - initialSeq = sequence; - state = MqttKafkaState.closeInitial(state); - - assert initialAck <= initialSeq; - - delegate.doKafkaEnd(traceId, initialSeq, authorization); - } - - private void onMqttAbort( - AbortFW abort) - { - final long sequence = abort.sequence(); - final long acknowledge = abort.acknowledge(); - final long traceId = abort.traceId(); - final long authorization = abort.authorization(); - - assert acknowledge <= sequence; - assert sequence >= initialSeq; - - initialSeq = sequence; - state = MqttKafkaState.closeInitial(state); - - assert initialAck <= initialSeq; - - delegate.doKafkaAbort(traceId, authorization); - } - - private void onMqttReset( - ResetFW reset) - { - final long sequence = reset.sequence(); - final long acknowledge = reset.acknowledge(); - final int maximum = reset.maximum(); - final long traceId = reset.traceId(); - - assert acknowledge <= sequence; - assert sequence <= replySeq; - assert acknowledge >= replyAck; - assert maximum >= replyMax; - - replyAck = acknowledge; - replyMax = maximum; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - delegate.doKafkaReset(traceId); - } - - private void onMqttWindow( - WindowFW window) - { - final long sequence = window.sequence(); - final long acknowledge = window.acknowledge(); - final int maximum = window.maximum(); - final long traceId = window.traceId(); - final long authorization = window.authorization(); - final long budgetId = window.budgetId(); - final int padding = window.padding(); - final int capabilities = window.capabilities(); - - assert acknowledge <= sequence; - assert sequence <= replySeq; - assert acknowledge >= replyAck; - assert maximum >= replyMax; - - replyAck = acknowledge; - replyMax = maximum; - replyPad = padding; - state = MqttKafkaState.openReply(state); - - assert replyAck <= replySeq; - - delegate.doKafkaWindow(traceId, authorization, budgetId, padding, capabilities); - } - - private void doMqttBegin( - long traceId, - long authorization, - long affinity) - { - replySeq = delegate.replySeq; - replyAck = delegate.replyAck; - replyMax = delegate.replyMax; - state = MqttKafkaState.openingReply(state); - - doBegin(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, affinity); - } - - private void doMqttData( - long traceId, - long authorization, - long budgetId, - int reserved, - int flags, - OctetsFW payload, - Flyweight extension) - { - doData(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); - - replySeq += reserved; - - assert replySeq <= replyAck + replyMax; - } - - private void doMqttFlush( - long traceId, - long authorization, - long budgetId, - int reserved) - { - replySeq = delegate.replySeq; - - doFlush(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, reserved, emptyRO); - } - - private void doMqttAbort( - long traceId, - long authorization) - { - if (!MqttKafkaState.replyClosed(state)) - { - replySeq = delegate.replySeq; - state = MqttKafkaState.closeReply(state); - - doAbort(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); - } - } - - private void doMqttEnd( - long traceId, - long authorization) - { - if (!MqttKafkaState.replyClosed(state)) - { - replySeq = delegate.replySeq; - state = MqttKafkaState.closeReply(state); - - doEnd(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); - } - } - - private void doMqttWindow( - long authorization, - long traceId, - long budgetId, - int padding, - int capabilities) - { - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - - doWindow(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, padding, 0, capabilities); - } - - private void doMqttReset( - long traceId) - { - if (!MqttKafkaState.initialClosed(state)) - { - state = MqttKafkaState.closeInitial(state); - - doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId); - } - } - } - - final class KafkaProxy - { - private MessageConsumer kafka; - private final long originId; - private final long routedId; - private final long initialId; - private final long replyId; - private final MqttSubscribeProxy delegate; - - private int state; - - private long initialSeq; - private long initialAck; - private int initialMax; - - private long replySeq; - private long replyAck; - private int replyMax; - private int replyPad; - - private KafkaProxy( - long originId, - long routedId, - MqttSubscribeProxy delegate) - { - this.originId = originId; - this.routedId = routedId; - this.delegate = delegate; - this.initialId = supplyInitialId.applyAsLong(routedId); - this.replyId = supplyReplyId.applyAsLong(initialId); - } - - private void doKafkaBegin( - long traceId, - long authorization, - long affinity) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.openingInitial(state); - - kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity); - } - - private void doKafkaFlush( - long traceId, - long authorization, - long budgetId, - int reserved, - Flyweight extension) - { - initialSeq = delegate.initialSeq; - - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, extension); - } - - private void doKafkaEnd( - long traceId, - long sequence, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void doKafkaAbort( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void onKafkaMessage( - int msgTypeId, - DirectBuffer buffer, - int index, - int length) - { - switch (msgTypeId) - { - case BeginFW.TYPE_ID: - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - onKafkaBegin(begin); - break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onKafkaData(data); - break; - case EndFW.TYPE_ID: - final EndFW end = endRO.wrap(buffer, index, index + length); - onKafkaEnd(end); - break; - case AbortFW.TYPE_ID: - final AbortFW abort = abortRO.wrap(buffer, index, index + length); - onKafkaAbort(abort); - break; - case FlushFW.TYPE_ID: - final FlushFW flush = flushRO.wrap(buffer, index, index + length); - onKafkaFlush(flush); - break; - case WindowFW.TYPE_ID: - final WindowFW window = windowRO.wrap(buffer, index, index + length); - onKafkaWindow(window); - break; - case ResetFW.TYPE_ID: - final ResetFW reset = resetRO.wrap(buffer, index, index + length); - onKafkaReset(reset); - break; - } - } - - private void onKafkaBegin( - BeginFW begin) - { - final long sequence = begin.sequence(); - final long acknowledge = begin.acknowledge(); - final int maximum = begin.maximum(); - final long traceId = begin.traceId(); - final long authorization = begin.authorization(); - final long affinity = begin.affinity(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - assert acknowledge >= replyAck; - - replySeq = sequence; - replyAck = acknowledge; - replyMax = maximum; - state = MqttKafkaState.openingReply(state); - - assert replyAck <= replySeq; - - delegate.doMqttBegin(traceId, authorization, affinity); - } - - private void onKafkaData( - DataFW data) - { - final long sequence = data.sequence(); - final long acknowledge = data.acknowledge(); - final long traceId = data.traceId(); - final long authorization = data.authorization(); - final long budgetId = data.budgetId(); - final int reserved = data.reserved(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence + reserved; - - assert replyAck <= replySeq; - - if (replySeq > replyAck + replyMax) - { - doKafkaReset(traceId); - delegate.doMqttAbort(traceId, authorization); - } - else - { - final int flags = data.flags(); - final OctetsFW payload = data.payload(); - final OctetsFW extension = data.extension(); - final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); - final KafkaDataExFW kafkaDataEx = - dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; - final KafkaMergedDataExFW kafkaMergedDataEx = - kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; - final Array32FW progress = kafkaMergedDataEx != null ? kafkaMergedDataEx.progress() : null; - final OctetsFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key().value() : null; - final Array32FW headers = kafkaMergedDataEx != null ? kafkaMergedDataEx.headers() : null; - //TODO: data - final long filters = kafkaMergedDataEx != null ? kafkaMergedDataEx.filters() : 0; - - if (key != null) - { - String topicName = kafkaMergedDataEx.key().value() - .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)); - helper.visit(kafkaMergedDataEx); - final Flyweight mqttSubscribeDataEx = mqttDataExRW.wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(mqttTypeId) - .subscribe(b -> - { - b.topic(topicName); - for (int i = 0; i < subscriptionIds.size(); i++) - { - if (((filters >> i) & 1) == 1) - { - int index = i; - b.subscriptionIdsItem(c -> c.set(subscriptionIds.get(index))); - } - } - if (helper.timeout != -1) - { - b.expiryInterval(helper.timeout / 1000); - } - if (helper.contentType != null) - { - b.contentType( - helper.contentType.buffer(), helper.contentType.offset(), helper.contentType.sizeof()); - } - if (helper.format != null) - { - b.format(f -> f.set(MqttPayloadFormat.valueOf(helper.format))); - } - if (helper.replyTo != null) - { - b.responseTopic( - helper.replyTo.buffer(), helper.replyTo.offset(), helper.replyTo.sizeof()); - } - if (helper.correlation != null) - { - b.correlation(c -> c.bytes(helper.correlation)); - } - - final DirectBuffer buffer = kafkaMergedDataEx.buffer(); - final int limit = kafkaMergedDataEx.limit(); - helper.userPropertiesOffsets.forEach(o -> - { - final KafkaHeaderFW header = kafkaHeaderRO.wrap(buffer, o, limit); - final OctetsFW name = header.name(); - final OctetsFW value = header.value(); - if (value != null) - { - b.propertiesItem(pi -> pi - .key(name.buffer(), name.offset(), name.sizeof()) - .value(value.buffer(), value.offset(), value.sizeof())); - } - }); - }).build(); - - delegate.doMqttData(traceId, authorization, budgetId, reserved, flags, payload, mqttSubscribeDataEx); - } - } - } - - private void onKafkaEnd( - EndFW end) - { - final long sequence = end.sequence(); - final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - delegate.doMqttEnd(traceId, authorization); - } - - private void onKafkaFlush( - FlushFW flush) - { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - final long budgetId = flush.budgetId(); - final int reserved = flush.reserved(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - - assert replyAck <= replySeq; - - delegate.doMqttFlush(traceId, authorization, budgetId, reserved); - } - - private void onKafkaAbort( - AbortFW abort) - { - final long sequence = abort.sequence(); - final long acknowledge = abort.acknowledge(); - final long traceId = abort.traceId(); - final long authorization = abort.authorization(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - delegate.doMqttAbort(traceId, authorization); - } - - private void onKafkaWindow( - WindowFW window) - { - final long sequence = window.sequence(); - final long acknowledge = window.acknowledge(); - final int maximum = window.maximum(); - final long authorization = window.authorization(); - final long traceId = window.traceId(); - final long budgetId = window.budgetId(); - final int padding = window.padding(); - final int capabilities = window.capabilities(); - - assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; - assert maximum >= delegate.initialMax; - - initialAck = acknowledge; - initialMax = maximum; - state = MqttKafkaState.openInitial(state); - - assert initialAck <= initialSeq; - - delegate.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); - } - - private void onKafkaReset( - ResetFW reset) - { - final long sequence = reset.sequence(); - final long acknowledge = reset.acknowledge(); - final long traceId = reset.traceId(); - - assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; - - delegate.initialAck = acknowledge; - - assert delegate.initialAck <= delegate.initialSeq; - - delegate.doMqttReset(traceId); - } - - private void doKafkaReset( - long traceId) - { - if (!MqttKafkaState.replyClosed(state)) - { - state = MqttKafkaState.closeReply(state); - - doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId); - } - } - - private void doKafkaWindow( - long traceId, - long authorization, - long budgetId, - int padding, - int capabilities) - { - replyAck = delegate.replyAck; - replyMax = delegate.replyMax; - replyPad = delegate.replyPad; - - doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, padding, replyPad, capabilities); - } - } - - - private void doBegin( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long affinity) - { - final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .affinity(affinity) - .build(); - - receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); - } - - private void doData( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long budgetId, - int flags, - int reserved, - OctetsFW payload, - Flyweight extension) - { - final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .flags(flags) - .budgetId(budgetId) - .reserved(reserved) - .payload(payload) - .extension(extension.buffer(), extension.offset(), extension.sizeof()) - .build(); - - receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); - } - - private void doEnd( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization) - { - final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .build(); - - receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); - } - - private void doAbort( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization) - { - final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .build(); - - receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); - } - - private void doFlush( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long budgetId, - int reserved, - Flyweight extension) - { - final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .budgetId(budgetId) - .reserved(reserved) - .extension(extension.buffer(), extension.offset(), extension.sizeof()) - .build(); - - receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); - } - - private MessageConsumer newKafkaStream( - MessageConsumer sender, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long affinity) - { - final KafkaBeginExFW kafkaBeginEx = - kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> - { - m.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); - m.topic(kafkaMessagesTopicName); - m.partitionsItem(p -> - p.partitionId(-1) - .partitionOffset(-1L)); - filters.forEach(filter -> - - m.filtersItem(f -> - { - f.conditionsItem(ci -> - { - subscriptionIds.add((int) filter.subscriptionId()); - buildHeaders(ci, filter.pattern().asString()); - }); - boolean noLocal = (filter.flags() & NO_LOCAL_FLAG) != 0; - if (noLocal) - { - final DirectBuffer valueBuffer = new String16FW(clientId).value(); - f.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> - h.nameLen(helper.kafkaLocalHeaderName.sizeof()) - .name(helper.kafkaLocalHeaderName) - .valueLen(valueBuffer.capacity()) - .value(valueBuffer, 0, valueBuffer.capacity()))))); - } - })); - m.evaluation(b -> b.set(KafkaEvaluation.EAGER)); - }) - .build(); - - - final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .affinity(affinity) - .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) - .build(); - - MessageConsumer receiver = - streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); - - receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); - - return receiver; - } - - private void buildHeaders( - KafkaConditionFW.Builder conditionBuilder, - String pattern) - { - String[] headers = pattern.split("/"); - conditionBuilder.headers(hb -> - { - hb.nameLen(helper.kafkaTopicHeaderName.sizeof()); - hb.name(helper.kafkaTopicHeaderName); - for (String header : headers) - { - if (header.equals(MQTT_SINGLE_LEVEL_WILDCARD)) - { - hb.valuesItem(vi -> vi.skip(sb -> sb.set(KafkaSkip.SKIP))); - } - else if (header.equals(MQTT_MULTI_LEVEL_WILDCARD)) - { - hb.valuesItem(vi -> vi.skip(sb -> sb.set(KafkaSkip.SKIP_MANY))); - } - else - { - final DirectBuffer valueBuffer = new String16FW(header).value(); - hb.valuesItem(vi -> vi.value(vb -> vb.length(valueBuffer.capacity()) - .value(valueBuffer, 0, valueBuffer.capacity()))); - - } - } - }); - } - - private void doWindow( - MessageConsumer sender, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long budgetId, - int padding, - int minimum, - int capabilities) - { - final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .budgetId(budgetId) - .padding(padding) - .minimum(minimum) - .capabilities(capabilities) - .build(); - - sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); - } - - private void doReset( - MessageConsumer sender, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId) - { - final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .build(); - - sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); - } -} diff --git a/incubator/binding-mqtt-kafka/src/main/moditect/module-info.java b/incubator/binding-mqtt-kafka/src/main/moditect/module-info.java deleted file mode 100644 index 2fe3bda1fa..0000000000 --- a/incubator/binding-mqtt-kafka/src/main/moditect/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -module io.aklivity.zilla.runtime.binding.mqtt.kafka -{ - requires io.aklivity.zilla.runtime.engine; - - provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi - with io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaBindingFactorySpi; - - provides io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi - with io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaConditionConfigAdapter; - -} diff --git a/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java b/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java deleted file mode 100644 index 132459d1c4..0000000000 --- a/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; - -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; - -public class MqttKafkaPublishProxyIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("mqtt", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt") - .addScriptRoot("kafka", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config") - .external("kafka0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.client.sent.abort/client", - "${kafka}/publish.client.sent.abort/server"}) - public void shouldReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.client.sent.reset/client", - "${kafka}/publish.client.sent.reset/server"}) - public void shouldReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.server.sent.abort/client", - "${kafka}/publish.server.sent.abort/server"}) - public void shouldReceiveServerSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.server.sent.flush/client", - "${kafka}/publish.server.sent.flush/server"}) - public void shouldReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.server.sent.reset/client", - "${kafka}/publish.server.sent.reset/server"}) - public void shouldReceiveServerSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.server.sent.data/client", - "${kafka}/publish.server.sent.data/server"}) - public void shouldAbortWhenServerSentData() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.one.message/client", - "${kafka}/publish.one.message/server"}) - public void shouldSendOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.empty.message/client", - "${kafka}/publish.empty.message/server"}) - public void shouldSendEmptyMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.multiple.messages/client", - "${kafka}/publish.multiple.messages/server"}) - public void shouldSendMultipleMessages() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.with.user.property/client", - "${kafka}/publish.with.user.property/server"}) - public void shouldSendWithUserProperty() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.with.user.properties.distinct/client", - "${kafka}/publish.with.user.properties.distinct/server"}) - public void shouldSendWithDistinctUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/publish.with.user.properties.repeated/client", - "${kafka}/publish.with.user.properties.repeated/server"}) - public void shouldSendWithRepeatedUserProperties() throws Exception - { - k3po.finish(); - } - -} diff --git a/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeProxyIT.java b/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeProxyIT.java deleted file mode 100644 index bc646e6e76..0000000000 --- a/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeProxyIT.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; - -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; - -public class MqttKafkaSubscribeProxyIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("mqtt", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt") - .addScriptRoot("kafka", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config") - .external("kafka0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.client.sent.abort/client", - "${kafka}/subscribe.client.sent.abort/server"}) - public void shouldReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.client.sent.data/client", - "${kafka}/subscribe.client.sent.data/server"}) - public void shouldAbortWhenClientSentData() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.client.sent.reset/client", - "${kafka}/subscribe.client.sent.reset/server"}) - public void shouldReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.server.sent.abort/client", - "${kafka}/subscribe.server.sent.abort/server"}) - public void shouldReceiveServerSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.server.sent.flush/client", - "${kafka}/subscribe.server.sent.flush/server"}) - public void shouldReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.server.sent.reset/client", - "${kafka}/subscribe.server.sent.reset/server"}) - public void shouldReceiveServerSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.one.message/client", - "${kafka}/subscribe.one.message/server"}) - public void shouldReceiveOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.one.message.receive.response.topic.and.correlation.data/client", - "${kafka}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) - public void shouldReceiveCorrelationData() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.one.message.user.properties.unaltered/client", - "${kafka}/subscribe.one.message.user.properties.unaltered/server"}) - public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.publish.no.local/client", - "${kafka}/subscribe.publish.no.local/server"}) - public void shouldNotReceiveLocal() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.receive.message.overlapping.wildcard/client", - "${kafka}/subscribe.receive.message.overlapping.wildcard/server"}) - public void shouldReceiveMessageOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.receive.message.wildcard/client", - "${kafka}/subscribe.receive.message.wildcard/server"}) - public void shouldReceiveOneMessageWithPatternTopic() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filter.multi.level.wildcard/client", - "${kafka}/subscribe.topic.filter.multi.level.wildcard/server"}) - public void shouldFilterMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filter.single.and.multi.level.wildcard/client", - "${kafka}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) - public void shouldFilterSingleAndMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filter.single.level.wildcard/client", - "${kafka}/subscribe.topic.filter.single.level.wildcard/server"}) - public void shouldFilterSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filter.two.single.level.wildcard/client", - "${kafka}/subscribe.topic.filter.two.single.level.wildcard/server"}) - public void shouldFilterTwoSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filters.aggregated.both.exact/client", - "${kafka}/subscribe.topic.filters.aggregated.both.exact/server"}) - public void shouldFilterAggregatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", - "${kafka}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) - public void shouldFilterAggregatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filters.isolated.both.exact/client", - "${kafka}/subscribe.topic.filters.isolated.both.exact/server"}) - public void shouldFilterIsolatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filters.isolated.exact.and.wildcard/client", - "${kafka}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) - public void shouldFilterIsolatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/subscribe.topic.filters.overlapping.wildcards/client", - "${kafka}/subscribe.topic.filters.overlapping.wildcards/server"}) - public void shouldFilterOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/unsubscribe.after.subscribe/client", - "${kafka}/unsubscribe.after.subscribe/server"}) - public void shouldAcknowledge() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("proxy.yaml") - @Specification({ - "${mqtt}/unsubscribe.topic.filter.single/client", - "${kafka}/unsubscribe.topic.filter.single/server"}) - public void shouldAcknowledgeSingleTopicFilter() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/pom.xml b/incubator/binding-mqtt.spec/pom.xml deleted file mode 100644 index af964a16db..0000000000 --- a/incubator/binding-mqtt.spec/pom.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - - 4.0.0 - - io.aklivity.zilla - incubator - 0.9.51 - ../pom.xml - - - binding-mqtt.spec - zilla::incubator::binding-mqtt.spec - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - 11 - 11 - 0.94 - 0 - - - - - org.kaazing - k3po.lang - provided - - - ${project.groupId} - engine.spec - ${project.version} - - - junit - junit - test - - - org.kaazing - k3po.junit - test - - - org.hamcrest - hamcrest-library - test - - - - - - - src/main/resources - - - src/main/scripts - - - - - - org.jasig.maven - maven-notice-plugin - - - ${project.groupId} - flyweight-maven-plugin - ${project.version} - - core mqtt - io.aklivity.zilla.specs.binding.mqtt.internal.types - - - - - validate - generate - - - - - - com.mycila - license-maven-plugin - - - maven-checkstyle-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.moditect - moditect-maven-plugin - - - org.kaazing - k3po-maven-plugin - - - ${project.groupId} - engine - ${project.version} - test-jar - - - ${project.groupId} - engine - ${project.version} - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.jacoco - jacoco-maven-plugin - - - io/aklivity/zilla/specs/binding/mqtt/internal/types/**/*.class - - - - BUNDLE - - - INSTRUCTION - COVEREDRATIO - ${jacoco.coverage.ratio} - - - CLASS - MISSEDCOUNT - ${jacoco.missed.count} - - - - - - - - - diff --git a/incubator/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl b/incubator/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl deleted file mode 100644 index a4718e0f40..0000000000 --- a/incubator/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -scope mqtt -{ - enum MqttSubscribeFlags (uint8) - { - SEND_RETAINED(0), - RETAIN_AS_PUBLISHED(1), - NO_LOCAL(2), - RETAIN(3) - } - - enum MqttQoS (uint8) - { - AT_MOST_ONCE(0), - AT_LEAST_ONCE(1), - EXACTLY_ONCE(2) - } - - enum MqttPublishFlags (uint8) - { - RETAIN(0) - } - - enum MqttCapabilities (uint8) - { - PUBLISH_ONLY(1), - SUBSCRIBE_ONLY(2), - SESSION(3) - } - - enum MqttEndReasonCode (uint8) - { - DISCONNECT(0), - KEEP_ALIVE_EXPIRY(1), - DISCONNECT_WITH_WILL(2) - } - - enum MqttPayloadFormat - { - BINARY, - TEXT - } - - struct MqttBinary - { - int32 length; - octets[length] bytes = null; - } - - struct MqttUserProperty - { - string16 key; - string16 value; - } - - struct MqttTopicFilter - { - uint32 subscriptionId = 0; - uint8 qos = 0; - uint8 flags = 1; - string16 pattern; - } - - struct MqttSessionState - { - string16 clientId; - MqttTopicFilter[] subscriptions; - } - - struct MqttMessage - { - string16 topic = null; - int32 delay = 0; - uint8 qos = 0; - uint8 flags = 0; - int32 expiryInterval = -1; - string16 contentType = null; - MqttPayloadFormat format = BINARY; - string16 responseTopic = null; - MqttBinary correlation; - MqttUserProperty[] properties; - MqttBinary payload; - } - - scope stream - { - enum MqttExtensionKind (uint8) - { - SESSION (2), - SUBSCRIBE (1), - PUBLISH (0) - } - - union MqttBeginEx switch (uint8) extends core::stream::Extension - { - case 0: mqtt::stream::MqttPublishBeginEx publish; - case 1: mqtt::stream::MqttSubscribeBeginEx subscribe; - case 2: mqtt::stream::MqttSessionBeginEx session; - } - - struct MqttSessionBeginEx - { - string16 clientId; - int32 expiry = 0; - MqttMessage will; - } - - struct MqttSubscribeBeginEx - { - string16 clientId; - MqttTopicFilter[] filters; - } - - struct MqttPublishBeginEx - { - string16 clientId; - string16 topic; - } - - union MqttDataEx switch (uint8) extends core::stream::Extension - { - case 0: mqtt::stream::MqttPublishDataEx publish; - case 1: mqtt::stream::MqttSubscribeDataEx subscribe; - } - - struct MqttSubscribeDataEx - { - int32 deferred = 0; // INIT only (TODO: move to DATA frame) - string16 topic = null; - uint8 qos = 0; - uint8 flags = 0; - varuint32[] subscriptionIds; - int32 expiryInterval = -1; - string16 contentType = null; - MqttPayloadFormat format = BINARY; - string16 responseTopic = null; - MqttBinary correlation; - MqttUserProperty[] properties; - } - - struct MqttPublishDataEx - { - int32 deferred = 0; // INIT only (TODO: move to DATA frame) - string16 topic = null; - uint8 qos = 0; - uint8 flags = 0; - int32 expiryInterval = -1; - string16 contentType = null; - MqttPayloadFormat format = BINARY; - string16 responseTopic = null; - MqttBinary correlation; - MqttUserProperty[] properties; - } - - struct MqttEndEx extends core::stream::Extension - { - MqttEndReasonCode reasonCode = DISCONNECT; - } - - union MqttFlushEx switch (uint8) extends core::stream::Extension - { - case 1: mqtt::stream::MqttSubscribeFlushEx subscribe; - } - - struct MqttSubscribeFlushEx - { - MqttTopicFilter[] filters; - } - } -} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.sessions.yaml b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.sessions.yaml deleted file mode 100644 index 1b38a58862..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.sessions.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - ---- -name: test -bindings: - net0: - type: mqtt - kind: server - routes: - - exit: app0 - when: - - capabilities: session diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.publish.only.yaml b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.publish.only.yaml deleted file mode 100644 index 2d55dc5836..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.publish.only.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - ---- -name: test -bindings: - net0: - type: mqtt - kind: server - routes: - - exit: app0 - when: - - topic: sensor/one - capabilities: publish diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.subscribe.only.yaml b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.subscribe.only.yaml deleted file mode 100644 index b6ab15bf65..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.subscribe.only.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - ---- -name: test -bindings: - net0: - type: mqtt - kind: server - routes: - - exit: app0 - when: - - topic: sensor/one - capabilities: subscribe diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.yaml b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.yaml deleted file mode 100644 index 765e5b4c09..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.when.topic.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - ---- -name: test -bindings: - net0: - type: mqtt - kind: server - routes: - - exit: app0 - when: - - topic: sensor/one diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json deleted file mode 100644 index 21575a7bcd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json +++ /dev/null @@ -1,87 +0,0 @@ -[ - { - "op": "add", - "path": "/$defs/binding/properties/type/enum/-", - "value": "mqtt" - }, - { - "op": "add", - "path": "/$defs/binding/allOf/-", - "value": - { - "if": - { - "properties": - { - "type": - { - "const": "mqtt" - } - } - }, - "then": - { - "properties": - { - "type": - { - "const": "mqtt" - }, - "kind": - { - "enum": [ "server" ] - }, - "vault": false, - "options": false, - "routes": - { - "items": - { - "properties": - { - "when": - { - "items": - { - "additionalProperties": false, - "properties": - { - "topic": - { - "title": "Topic", - "type": "string" - }, - "capabilities": - { - "title": "Capabilities", - "type": "string", - "enum": [ "session", "publish", "subscribe", "publish_and_subscribe" ], - "default": "publish_and_subscribe" - } - } - } - }, - "with": false - } - } - } - }, - "anyOf": - [ - { - "required": - [ - "exit" - ] - }, - { - "required": - [ - "routes" - ] - } - ] - } - } - } -] diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt deleted file mode 100644 index 42bd77a5c9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -connected - -write abort diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt deleted file mode 100644 index 128b64c61c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -connected - -read aborted diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt deleted file mode 100644 index 6add586d14..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .build() - .build()} - -read "message that should not arrive to client, since it exceeds max packet limit" - - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt deleted file mode 100644 index fe0b5d0540..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .build() - .build()} - -write "message that should not arrive to client, since it exceeds max packet limit" -write flush - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt deleted file mode 100644 index 9218fc2e2b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} -write zilla:data.empty -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt deleted file mode 100644 index a6480e979d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt deleted file mode 100644 index 56622b6ab3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} -write zilla:data.empty -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt deleted file mode 100644 index a73248bd47..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt deleted file mode 100644 index 8a47c697ab..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt deleted file mode 100644 index 97a141e137..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt deleted file mode 100644 index 55f81d6eb8..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt +++ /dev/null @@ -1,79 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message1" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message3" - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/two") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -write "message2" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -write "message4" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt deleted file mode 100644 index e5908d22bf..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt +++ /dev/null @@ -1,81 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message1" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message3" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/two") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -read "message2" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .qos("AT_MOST_ONCE") - .build() - .build()} - -read "message4" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt deleted file mode 100644 index 1c75847256..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message1" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message2" - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt deleted file mode 100644 index 8684321d2f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message1" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message2" - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt deleted file mode 100644 index a5967e8832..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message1" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message2" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message3" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt deleted file mode 100644 index aefdff5a25..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message1" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message2" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message3" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt deleted file mode 100644 index 0beb41c4a2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt +++ /dev/null @@ -1,70 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message1" - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/two") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -write "message2" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -write "message3" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt deleted file mode 100644 index 984617ccd3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt +++ /dev/null @@ -1,72 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message1" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/two") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -read "message2" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -read "message3" - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt deleted file mode 100644 index af278c7e21..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message1" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "test" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -write "message3" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt deleted file mode 100644 index 635bc856e7..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message1" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "test" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .build() - .build()} - -read "message3" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/client.rpt deleted file mode 100644 index bf770b1dd7..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/client.rpt +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -write "message" - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -write "message2" - -write notify PUBLISHED - -connect await PUBLISHED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/two", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/server.rpt deleted file mode 100644 index 1e5af8308b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/server.rpt +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -read "message" - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -read "message2" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/two", 1) - .build() - .build()} - -connected - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/client.rpt deleted file mode 100644 index f650efd701..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/client.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -write "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/server.rpt deleted file mode 100644 index d23c11c3cd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .qos("AT_MOST_ONCE") - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt deleted file mode 100644 index 4fc78dd93d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} - -write "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt deleted file mode 100644 index 74f758d9c5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt deleted file mode 100644 index be574df74d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("/sensors/1") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("/sensors/1") - .userProperty("row1", "1") - .userProperty("row2", "2") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt deleted file mode 100644 index cc503e4eec..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("/sensors/1") - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("/sensors/1") - .userProperty("row1", "1") - .userProperty("row2", "2") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt deleted file mode 100644 index 4a45d83c7b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("/sensors/1") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("/sensors/1") - .userProperty("row1", "1") - .userProperty("row1", "2") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt deleted file mode 100644 index 5bf728ae4c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("/sensors/1") - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("/sensors/1") - .userProperty("row1", "1") - .userProperty("row1", "2") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt deleted file mode 100644 index f29fccc076..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("/sensors/1") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("/sensors/1") - .userProperty("row", "1") - .build() - .build()} - -write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt deleted file mode 100644 index dad063c03d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") - .topic("/sensors/1") - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("/sensors/1") - .userProperty("row", "1") - .build() - .build()} - -read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt deleted file mode 100644 index a5432b0a7d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt +++ /dev/null @@ -1,109 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read zilla:data.empty - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write abort -write notify SESSION_READY - - -connect await SESSION_READY - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} -connected - -write abort -write notify ABORTED - - -connect await ABORTED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write notify SESSION_READY2 - -connect await SESSION_READY2 - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt deleted file mode 100644 index 81c799aa72..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt +++ /dev/null @@ -1,102 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - - -read aborted - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read aborted - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt deleted file mode 100644 index d79c901aa3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt +++ /dev/null @@ -1,110 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write notify FIRST_CONNECTED - -read closed -write close - -connect await FIRST_CONNECTED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} -connected - -write close -read closed - -write notify DISCONNECTED - - -connect await DISCONNECTED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write notify SESSION_READY2 - -connect await SESSION_READY2 - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt deleted file mode 100644 index 81dc1dedde..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -read await CLIENT_TAKEOVER - -write close -read closed - - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read closed -write close - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write notify CLIENT_TAKEOVER - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt deleted file mode 100644 index 7c06e2e3a0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .expiry(1) - .build() - .build()} -connected - -read zilla:data.empty diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt deleted file mode 100644 index 113f780150..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .expiry(1) - .build() - .build()} -connected - -write zilla:data.empty -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt deleted file mode 100644 index 26a9a80ed1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt +++ /dev/null @@ -1,88 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read zilla:data.empty - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write notify CLIENT_TAKEOVER - -read closed -write close - -write notify SESSION_READY - -connect await SESSION_READY - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write close -read closed - -connect await SESSION_READY - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write zilla:data.empty diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt deleted file mode 100644 index 026b97886b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt +++ /dev/null @@ -1,84 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -read await CLIENT_TAKEOVER - -write close -read closed - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read closed -write close - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -read zilla:data.empty -write notify CLIENT_TAKEOVER diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt deleted file mode 100644 index 9ea474d72b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read zilla:data.empty - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one") - .build()} - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt deleted file mode 100644 index e24c364374..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one") - .build()} -write flush - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt deleted file mode 100644 index ac18737ae1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read zilla:data.empty - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt deleted file mode 100644 index b40a5ad9a5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt deleted file mode 100644 index 781d702696..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read zilla:data.empty - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .subscription("sensor/two", 1) - .build()} - -write notify UNSUBSCRIBE_ALL_FILTERS -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .subscription("sensor/two", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .build()} - -read ${mqtt:session() - .clientId("client") - .build()} - -write notify SESSION_FINISHED - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/two", 1) - .build() - .build()} - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt deleted file mode 100644 index 113ba9999a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt +++ /dev/null @@ -1,79 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} -connected - -write zilla:data.empty -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .subscription("sensor/two", 1) - .build()} - -read await UNSUBSCRIBE_ALL_FILTERS -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .subscription("sensor/two", 1) - .build()} -write flush - -read ${mqtt:session() - .clientId("client") - .build()} - -write ${mqtt:session() - .clientId("client") - .build()} -write flush - - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/two", 1) - .build() - .build()} - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt deleted file mode 100644 index e9c72a820c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -read zilla:data.empty - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .build()} - -read ${mqtt:session() - .clientId("client") - .build()} - -write notify SESSION_READY - - -connect await SESSION_READY - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt deleted file mode 100644 index 9d0e5a0525..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -read ${mqtt:session() - .clientId("client") - .build()} - -write ${mqtt:session() - .clientId("client") - .build()} -write flush - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt deleted file mode 100644 index fb769fed46..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - - -read zilla:data.empty - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write notify SUBSCRIBED - -read ${mqtt:session() - .clientId("client") - .build()} - -write notify SESSION_READY - - -connect await SESSION_READY - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt deleted file mode 100644 index cf0094889c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt +++ /dev/null @@ -1,66 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("client") - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} - -write ${mqtt:session() - .clientId("client") - .subscription("sensor/one", 1) - .build()} -write flush - -read await SUBSCRIBED -write ${mqtt:session() - .clientId("client") - .build()} -write flush - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.disconnect.with.will.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.disconnect.with.will.message/client.rpt deleted file mode 100644 index 327eacf0dd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.disconnect.with.will.message/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -read zilla:data.empty - -write zilla:end.ext ${mqtt:endEx() - .typeId(zilla:id("mqtt")) - .reason("DISCONNECT_WITH_WILL") - .build()} - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.disconnect.with.will.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.disconnect.with.will.message/server.rpt deleted file mode 100644 index 7fa2aa8b91..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.disconnect.with.will.message/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read zilla:end.ext ${mqtt:endEx() - .typeId(zilla:id("mqtt")) - .reason("DISCONNECT_WITH_WILL") - .build()} - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.no.ping.within.keep.alive/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.no.ping.within.keep.alive/client.rpt deleted file mode 100644 index 1a916fea30..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.no.ping.within.keep.alive/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -read zilla:data.empty - -write zilla:end.ext ${mqtt:endEx() - .typeId(zilla:id("mqtt")) - .reason("KEEP_ALIVE_EXPIRY") - .build()} - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.no.ping.within.keep.alive/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.no.ping.within.keep.alive/server.rpt deleted file mode 100644 index 7d09b0668c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.no.ping.within.keep.alive/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read zilla:end.ext ${mqtt:endEx() - .typeId(zilla:id("mqtt")) - .reason("KEEP_ALIVE_EXPIRY") - .build()} - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt deleted file mode 100644 index 108080f362..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -read zilla:data.empty - -write zilla:end.ext ${mqtt:endEx() - .typeId(zilla:id("mqtt")) - .reason("DISCONNECT") - .build()} - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt deleted file mode 100644 index 94489d98e3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -write zilla:data.empty -write flush - -read zilla:end.ext ${mqtt:endEx() - .typeId(zilla:id("mqtt")) - .reason("DISCONNECT") - .build()} - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt deleted file mode 100644 index ce41ce3f68..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .flags("RETAIN") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -read zilla:data.empty diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt deleted file mode 100644 index 7cbdb75f40..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .session() - .clientId("one") - .will() - .topic("wills/one") - .flags("RETAIN") - .format("TEXT") - .payload("client one session expired") - .build() - .build() - .build()} - -connected - -write zilla:data.empty -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt deleted file mode 100644 index 7ed66fc3ea..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt deleted file mode 100644 index 79ac93bf98..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt deleted file mode 100644 index 8bd244254b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt deleted file mode 100644 index f5bfae2423..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("sensor/one") - .correlation("info") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt deleted file mode 100644 index 6f76abc1cf..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .userProperty("row1", "1") - .userProperty("row1", "2") - .build() - .build()} - - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt deleted file mode 100644 index 857c759faa..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .userProperty("row1", "1") - .userProperty("row1", "2") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt deleted file mode 100644 index 2d946a1a43..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt deleted file mode 100644 index 4a5cdf05c0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt deleted file mode 100644 index 016b74d411..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt +++ /dev/null @@ -1,66 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL", "SEND_RETAINED") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -read "message2" - -write notify SUBSCRIBED - - -connect await SUBSCRIBED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} -write "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt deleted file mode 100644 index 7a05efdbe0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL", "SEND_RETAINED") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -write "message2" -write flush - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt deleted file mode 100644 index cbddf7285c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client2") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} - -write "message" -write flush - - -write notify PUBLISHED - -connect await PUBLISHED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client1") - .filter("sensor/one", 1, "AT_MOST_ONCE") - .build() - .build()} - -connected - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt deleted file mode 100644 index 42f1dcd638..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client2") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} - -read "message" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client1") - .filter("sensor/one", 1, "AT_MOST_ONCE") - .build() - .build()} - -connected - - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt deleted file mode 100644 index 83ec82fc6d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client1") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} - -write "message" -write flush -write notify RETAIN_PUBLISHED - -connect await RETAIN_PUBLISHED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client2") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt deleted file mode 100644 index 2e5df58b86..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client1") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} - -read "message" - - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client2") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt deleted file mode 100644 index e7f855d63f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/#", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/+/#", 1) - .filter("sensor/+/1", 2) - .build() - .build()} - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one/1") - .subscriptionId(1) - .subscriptionId(2) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt deleted file mode 100644 index fcb3fbf8b0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/#", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/+/#", 1) - .filter("sensor/+/1", 2) - .build() - .build()} - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one/1") - .subscriptionId(1) - .subscriptionId(2) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt deleted file mode 100644 index 74d45ce695..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+", 1) - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt deleted file mode 100644 index a13fc5d8dc..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt deleted file mode 100644 index 86006a1a7a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -read "message" - - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} -write "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt deleted file mode 100644 index f5f5b16fba..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} -write "message" - -accepted - -read zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/one") - .format("TEXT") - .build() - .build()} -read "message" - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt deleted file mode 100644 index 63d6ae8673..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt deleted file mode 100644 index 562ad9c206..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") - .build() - .build()} - -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .topic("sensor/one") - .flags("RETAIN") - .subscriptionId(1) - .format("TEXT") - .build() - .build()} - -write "message" -write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt deleted file mode 100644 index fd61ba9ff8..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt deleted file mode 100644 index 496fea1a0c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt deleted file mode 100644 index ed61885ebf..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/1/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt deleted file mode 100644 index 8a13815211..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/1/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt deleted file mode 100644 index 32c4bf265f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt deleted file mode 100644 index b2725ffb3c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt deleted file mode 100644 index 7d5f7d7bfb..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt deleted file mode 100644 index 997484b097..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt deleted file mode 100644 index a718e65d67..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/+", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt deleted file mode 100644 index 85e8ee4607..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/+", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt deleted file mode 100644 index bccc5a676f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt deleted file mode 100644 index 07dc698f05..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt deleted file mode 100644 index 8a716db1b7..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("device/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt deleted file mode 100644 index 8f18a8eb6d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("device/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt deleted file mode 100644 index 91ab3c94bb..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/#", 1) - .filter("device/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt deleted file mode 100644 index 3e87f226e0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/#", 1) - .filter("device/#", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt deleted file mode 100644 index 71f67b8c52..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/one", 1) - .filter("sensor/two", 2) - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt deleted file mode 100644 index 0e4e1a761a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/one", 1) - .filter("sensor/two", 2) - .build() - .build()} - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt deleted file mode 100644 index 127e186273..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/#", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/#", 1) - .filter("device/#", 2) - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt deleted file mode 100644 index d7a7bb2088..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/#", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/#", 1) - .filter("device/#", 2) - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt deleted file mode 100644 index f91aafaeb5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/one", 1) - .filter("device/#", 2) - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt deleted file mode 100644 index 1c11615786..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/one", 1) - .filter("device/#", 2) - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt deleted file mode 100644 index 4cf5f87625..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/#", 1) - .filter("sensor/+/1", 1) - .build() - .build()} - -connected diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt deleted file mode 100644 index 1661014959..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/+/#", 1) - .filter("sensor/+/1", 1) - .build() - .build()} - -connected - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt deleted file mode 100644 index 2863642652..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt deleted file mode 100644 index 06ce00f3e1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .build() - .build()} - -connected - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt deleted file mode 100644 index 3dc75793ec..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt deleted file mode 100644 index 5c00c727b7..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt deleted file mode 100644 index 71aa582a5f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/two", 1) - .build() - .build()} - -write notify SUBSCRIBED - -connect await SUBSCRIBED - "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/two") - .build() - .build()} -connected - -write zilla:data.ext ${mqtt:dataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -write "message" - - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt deleted file mode 100644 index 1c1780bb18..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/two", 1) - .build() - .build()} - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/two") - .build() - .build()} - -connected - -read zilla:data.ext ${mqtt:matchDataEx() - .typeId(zilla:id("mqtt")) - .publish() - .topic("sensor/two") - .build() - .build()} - -read "message" diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt deleted file mode 100644 index b1d4973ec3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -write advise zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/two", 1) - .build() - .build()} - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt deleted file mode 100644 index 99b60b0f54..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/app0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .clientId("client") - .filter("sensor/one", 1) - .filter("sensor/two", 1) - .build() - .build()} - -connected - -read advised zilla:flush ${mqtt:flushEx() - .typeId(zilla:id("mqtt")) - .subscribe() - .filter("sensor/two", 1) - .build() - .build()} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/client.rpt deleted file mode 100644 index e2ce9cf455..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/client.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write abort diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/server.rpt deleted file mode 100644 index 6712eeeb12..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/server.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read aborted diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/client.rpt deleted file mode 100644 index 17253032c3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/client.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/server.rpt deleted file mode 100644 index d1b4bfceb1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/server.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/client.rpt deleted file mode 100644 index 939934e70b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/client.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read abort diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/server.rpt deleted file mode 100644 index 199ed1b4e5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/server.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write aborted diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/client.rpt deleted file mode 100644 index a615fc32af..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/client.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - option zilla:byteorder "network" - -connected - -write [0x10 0x18] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x05] # properties = maximum packet size - [0x27] 50 # maximum packet size = 50 - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/server.rpt deleted file mode 100644 index 8c1619aedd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x18] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x05] # properties = maximum packet size - [0x27] 50 # maximum packet size = 50 - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt deleted file mode 100644 index a65921d8e9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -connected - -write [0x10 0x18] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x05] # properties = maximum packet size - [0x27 0x00 0x32] # maximum packet size = 50 - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x27] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x13] # properties - [0x0b 0x01] # subscription id = 1 - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt deleted file mode 100644 index 2821fc44de..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted -connected - -read [0x10 0x18] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x05] # properties = maximum packet size - [0x27 0x00 0x32] # maximum packet size = 50 - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x27] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x13] # properties - [0x0b 0x01] # subscription id = 1 - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/client.rpt deleted file mode 100644 index 18fcb7c354..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/client.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x24 0x00] # maximum qos = at most once diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/server.rpt deleted file mode 100644 index 4499d83b64..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/server.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x24 0x00] # maximum qos = at most once diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/client.rpt deleted file mode 100644 index d39897ba84..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/client.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x23] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x82] # flags = username, clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - [0x00 0x08] "username" # username - [0x00 0x08] "password" # password - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x81] # reason = malformed packet - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/server.rpt deleted file mode 100644 index e23f5550e2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/server.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x23] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x82] # flags = username, clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - [0x00 0x08] "username" # username - [0x00 0x08] "password" # password - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x81] # reason = malformed packet - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/client.rpt deleted file mode 100644 index 4716401c5a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason = success - [0x00] # properties = none - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x82] # reason = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/server.rpt deleted file mode 100644 index be588902cc..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason = success - [0x00] # properties = none - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x82] # reason = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/client.rpt deleted file mode 100644 index 242add14df..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/client.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x25 0x00] # retain unavailable diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/server.rpt deleted file mode 100644 index cdbb92a648..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/server.rpt +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x25 0x00] # retain unavailable diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/client.rpt deleted file mode 100644 index d3eaed1606..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/client.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x0d] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x00] # client id - -read [0x20 0x2a] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x27] # properties - [0x12 0x00 0x24] [0..36] # assigned clientId diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/server.rpt deleted file mode 100644 index f4e35b2b1e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -property assignedClientId "123e4567-e89b-42d3-a456-556642440000" - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x0d] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x00] # client id - -write [0x20 0x2a] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x27] # properties - [0x12 0x00 0x24] ${assignedClientId} # assigned clientId diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/client.rpt deleted file mode 100644 index 90b2c6b917..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties = server keep alive - [0x13] 10s # server keep alive = 10s - -read await WAIT_2_SECONDS - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/server.rpt deleted file mode 100644 index 3af4304ce1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/server.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties = server keep alive - [0x13] 10s # server keep alive = 10s - -write notify WAIT_2_SECONDS diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/client.rpt deleted file mode 100644 index 97d4de65a4..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - - [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/server.rpt deleted file mode 100644 index b2083f3c35..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/client.rpt deleted file mode 100644 index 11aab482ff..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/client.rpt +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name -write [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/server.rpt deleted file mode 100644 index 08b8a21115..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/server.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/client.rpt deleted file mode 100644 index 60cde0868b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/client.rpt +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/server.rpt deleted file mode 100644 index e7deccee13..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/server.rpt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/client.rpt deleted file mode 100644 index 4a82d8b390..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/client.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0xe0 0x02] # DISCONNECT - [0x8d] # reason = keep alive timeout - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/server.rpt deleted file mode 100644 index bfbcbf1ea5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/server.rpt +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0xe0 0x02] # DISCONNECT - [0x8d] # reason = keep alive timeout - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/client.rpt deleted file mode 100644 index 467424a17c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/client.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0xe1 0x02] # malformed DISCONNECT - [0x00] # normal disconnect - [0x00] # properties = none - -read [0xe0 0x02] # malformed DISCONNECT - [0x81] # malformed packet - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/server.rpt deleted file mode 100644 index 61ac0df492..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0xe1 0x02] # malformed DISCONNECT - [0x00] # normal disconnect - [0x00] # properties = none - -write [0xe0 0x02] # DISCONNECT - [0x81] # malformed packet - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/client.rpt deleted file mode 100644 index 0e4dccb94f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/client.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0xe0 0x02] # DISCONNECT - [0x00] # normal disconnect - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/server.rpt deleted file mode 100644 index 8e28b450c8..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/server.rpt +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0xe0 0x02] # DISCONNECT - [0x00] # normal disconnect - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/client.rpt deleted file mode 100644 index bfcdb1d156..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/client.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read await WAIT_1_SECOND - -write [0xc0 0x00] # PINGREQ - -read [0xd0 0x00] # PINGRESP - -read await WAIT_1_SECOND2 - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/server.rpt deleted file mode 100644 index 93437368e9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/server.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write notify WAIT_1_SECOND - -read [0xc0 0x00] # PINGREQ - -write [0xd0 0x00] # PINGRESP - -write notify WAIT_1_SECOND2 - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/client.rpt deleted file mode 100644 index 969c1907f5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x11] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x04] "abcd" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0xc0 0x00] # PINGREQ - -read [0xd0 0x00] # PINGRESP diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/server.rpt deleted file mode 100644 index dbe9b48291..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/server.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x11] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x04] "abcd" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0xc0 0x00] # PINGREQ - -write [0xd0 0x00] # PINGRESP diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/client.rpt deleted file mode 100644 index b035043ef2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x0d] # PUBLISH flags = at-most-once - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/server.rpt deleted file mode 100644 index c6835ad4bd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/server.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x0d] # PUBLISH flags = at-most-once - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/client.rpt deleted file mode 100644 index 8d2b0d7dc1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/client.rpt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x0d] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/server.rpt deleted file mode 100644 index a5a00b450f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/server.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x0d] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/client.rpt deleted file mode 100644 index b39fec144d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -write [0x30 0x17] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/server.rpt deleted file mode 100644 index bd6707ead1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/server.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -read [0x30 0x17] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/client.rpt deleted file mode 100644 index 59ea2e689b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/client.rpt +++ /dev/null @@ -1,84 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -connected - -write [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - -write notify PUBLISHED - -connect await PUBLISHED - "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -connected - -write [0x10 0x17] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client2" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/server.rpt deleted file mode 100644 index 382be31814..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/server.rpt +++ /dev/null @@ -1,80 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted -connected - -read [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - - -accepted -connected - -read [0x10 0x17] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client2" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/client.rpt deleted file mode 100644 index 7816cde38d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/client.rpt +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x02] # topic alias maximum = 2 - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 2s # topic alias maximum = 2 - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/two" # topic name - [0x03] # properties - [0x23 0x00 0x02] # topic alias = 2 - "message2" # payload - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x02] # topic alias = 2 - "message4" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/server.rpt deleted file mode 100644 index e3acfcf586..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/server.rpt +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x02] # topic alias maximum = 2 - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 2s # topic alias maximum = 2 - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/two" # topic name - [0x03] # properties - [0x23 0x00 0x02] # topic alias = 2 - "message2" # payload - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x02] # topic alias = 2 - "message4" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/client.rpt deleted file mode 100644 index f407519a5b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/client.rpt +++ /dev/null @@ -1,86 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - -write notify PUBLISHED - -connect await PUBLISHED - "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x17] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x07] "client2" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/server.rpt deleted file mode 100644 index 9253a6b7ef..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/server.rpt +++ /dev/null @@ -1,81 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - - -accepted -connected - -read [0x10 0x17] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x07] "client2" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/client.rpt deleted file mode 100644 index 842cf10a1a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/client.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/server.rpt deleted file mode 100644 index 535fe0eb68..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/server.rpt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/client.rpt deleted file mode 100644 index 5555adf084..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/client.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/two" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - -write [0x30 0x0e] # PUBLISH - [0x00 0x00] # empty topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/server.rpt deleted file mode 100644 index 63ac197384..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message1" # payload - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/two" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message2" # payload - -read [0x30 0x0e] # PUBLISH - [0x00 0x00] # topic name = empty - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message3" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/client.rpt deleted file mode 100644 index 6e2fca673e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/client.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message1" # payload - [0x30 0x11] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "test" # payload - [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message3" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/server.rpt deleted file mode 100644 index 2380868209..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message1" # payload - [0x30 0x11] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "test" # payload - [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message3" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/client.rpt deleted file mode 100644 index e179751732..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/client.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message1" # payload - -write [0x30 0x11] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "test" # payload - -write notify PUBLISHED_MESSAGE_TWO -write await PUBLISH_MESSAGE_THREE - -write [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message3" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/server.rpt deleted file mode 100644 index a0b2569596..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/server.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message1" # payload - -read [0x30 0x11] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "test" # payload - -read [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message3" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/client.rpt deleted file mode 100644 index ae7414919b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message1" # payload - -write [0x30 0x11] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "test" # payload - -write [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message3" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/server.rpt deleted file mode 100644 index a0b2569596..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/server.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message1" # payload - -read [0x30 0x11] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "test" # payload - -read [0x30 0x15] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message3" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/client.rpt deleted file mode 100644 index 214a953528..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/client.rpt +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x39] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - [0x30 0x3a] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message2" # payload - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/server.rpt deleted file mode 100644 index b91aec06c9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x39] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/client.rpt deleted file mode 100644 index 44a0e55da2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/client.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x39] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/server.rpt deleted file mode 100644 index 211a29685b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x39] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/client.rpt deleted file mode 100644 index ce2f3c1d7b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x28] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x12] # properties - [0x0b 0x01] # subscription id = 1 - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x0a] "text/plain" # content type - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x81] # reason = malformed packet - [0x00] # properties = none - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/server.rpt deleted file mode 100644 index 48bd9f4b0e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x28] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x12] # properties - [0x0b 0x01] # subscription id = 1 - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x0a] "text/plain" # content type - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x81] # reason = malformed packet - [0x00] # properties = none - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/client.rpt deleted file mode 100644 index bf56176077..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x36] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - [0xfe 0xfe 0xff 0xff] # payload - -read [0xe0 0x02] # DISCONNECT - [0x99] # payload format invalid - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/server.rpt deleted file mode 100644 index ad423bf5d9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x36] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - [0xfe 0xfe 0xff 0xff] # payload - -write [0xe0 0x02] # DISCONNECT - [0x99] # payload format invalid - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/client.rpt deleted file mode 100644 index aa6fe7845a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/client.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x3b] # PUBLISH, qos = at most once - [0x00 0x0a] "sensor/one" # topic name - [0x00 0x01] # packet id = 1 - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/server.rpt deleted file mode 100644 index 270f88990c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/server.rpt +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x3b] # PUBLISH, qos = at most once - [0x00 0x0a] "sensor/one" # topic name - [0x00 0x01] # packet id = 1 - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/client.rpt deleted file mode 100644 index e211184ae2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/client.rpt +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x24 0x00] # maximum qos = at most once - -write [0x32 0x39] # PUBLISH, qos = at least once - [0x00 0x0a] "sensor/one" # topic name - [0x00 0x01] # packet id = 1 - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x9b] # disconnect = QoS not supported - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/server.rpt deleted file mode 100644 index 4ece5acfa3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/server.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x24 0x00] # maximum qos = at most once - -read [0x32 0x39] # PUBLISH, qos = at least once - [0x00 0x0a] "sensor/one" # topic name - [0x00 0x01] # packet id = 1 - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x9b] # disconnect = QoS not supported - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/client.rpt deleted file mode 100644 index 42bbd0b808..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/client.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x32 0x39] # PUBLISH, qos = at least once - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/server.rpt deleted file mode 100644 index 5acb55f014..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/server.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x32 0x39] # PUBLISH, qos = at least once - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/client.rpt deleted file mode 100644 index a673d141f9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/client.rpt +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x24 0x00] # maximum qos = at most once - -write [0x34 0x39] # PUBLISH, qos = exactly once - [0x00 0x0a] "sensor/one" # topic name - [0x00 0x01] # packet id = 1 - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x9b] # disconnect = QoS not supported - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/server.rpt deleted file mode 100644 index 40970e6b00..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/server.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x24 0x00] # maximum qos = at most once - -read [0x34 0x39] # PUBLISH, qos = exactly once - [0x00 0x0a] "sensor/one" # topic name - [0x00 0x01] # packet id = 1 - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x9b] # disconnect = QoS not supported - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/client.rpt deleted file mode 100644 index c2a98921f4..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/client.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x34 0x39] # PUBLISH, qos = exactly once - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/server.rpt deleted file mode 100644 index 50dc4d2a37..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/server.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x34 0x39] # PUBLISH, qos = exactly once - [0x00 0x0a] "sensor/one" # topic name - [0x25] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/client.rpt deleted file mode 100644 index 01a18efe7f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x25 0x00] # retain unavailable - -write [0x31 0x26] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x12] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x0a] "text/plain" # content type - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x9a] # disconnect = retain not supported - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/server.rpt deleted file mode 100644 index 155185b854..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x25 0x00] # retain unavailable - -read [0x31 0x26] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x12] # properties - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x0a] "text/plain" # content type - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x9a] # disconnect = retain not supported - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/client.rpt deleted file mode 100644 index ce747d5f28..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x17] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x94] # disconnect = topic alias invalid - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/server.rpt deleted file mode 100644 index 30c71e3d95..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x17] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x03] # properties - [0x23 0x00 0x01] # topic alias = 1 - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x94] # disconnect = topic alias invalid - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/client.rpt deleted file mode 100644 index f0465d8ee5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -read [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -write [0x30 0x1a] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x06] # properties - [0x23 0x00 0x01] # topic alias = 1 - [0x23 0x00 0x01] # topic alias = 1 - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/server.rpt deleted file mode 100644 index be89b64955..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x16] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x03] # properties - [0x22 0x00 0x01] # topic alias maximum = 1 - [0x00 0x06] "client" # client id - -write [0x20 0x06] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x03] # properties - [0x22] 1s # topic alias maximum = 1 - -read [0x30 0x1a] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x06] # properties - [0x23 0x00 0x01] # topic alias = 1 - [0x23 0x00 0x01] # topic alias = 1 - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/client.rpt deleted file mode 100644 index 1cd14952d2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/client.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x14] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/server.rpt deleted file mode 100644 index 31fdbc9e16..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/server.rpt +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x14] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message" # payload - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/client.rpt deleted file mode 100644 index 2af757f188..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x15] # PUBLISH - [0x00 0x0b] "sensor/none" # topic name - [0x00] # properties = none - "message" # payload - -read [0xe0 0x02] # disconnect header - [0x90] # DISCONNECT = topic name invalid - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/server.rpt deleted file mode 100644 index 265527cf55..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x15] # PUBLISH - [0x00 0x0b] "sensor/none" # topic name - [0x00] # properties = none - "message" # payload - -write [0xe0 0x02] # disconnect header - [0x90] # DISCONNECT = topic name invalid - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/client.rpt deleted file mode 100644 index 35429cd5d6..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x4a] # PUBLISH - [0x00 0x0a] "/sensors/1" # topic name - [0x14] # properties - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "1" # user property value - [0x26] # user property id - [0x00 0x04] "row2" # user property key - [0x00 0x01] "2" # user property value - "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/server.rpt deleted file mode 100644 index 84e1702313..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x4a] # PUBLISH - [0x00 0x0a] "/sensors/1" # topic name - [0x14] # properties - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "1" # user property value - [0x26] # user property id - [0x00 0x04] "row2" # user property key - [0x00 0x01] "2" # user property value - "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/client.rpt deleted file mode 100644 index ba0327ee3f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x4a] # PUBLISH - [0x00 0x0a] "/sensors/1" # topic name - [0x14] # properties - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "1" # user property value - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "2" # user property value - "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/server.rpt deleted file mode 100644 index 1b5899fe62..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x4a] # PUBLISH - [0x00 0x0a] "/sensors/1" # topic name - [0x14] # properties - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "1" # user property value - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "2" # user property value - "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/client.rpt deleted file mode 100644 index 972f9f3f53..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/client.rpt +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x3f] # PUBLISH - [0x00 0x0a] "/sensors/1" # topic name - [0x09] # properties - [0x26] # user property id - [0x00 0x03] "row" # user property key - [0x00 0x01] "1" # user property value - "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/server.rpt deleted file mode 100644 index bc00e3d81e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/server.rpt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x3f] # PUBLISH - [0x00 0x0a] "/sensors/1" # topic name - [0x09] # properties - [0x26] # user property id - [0x00 0x03] "row" # user property key - [0x00 0x01] "1" # user property value - "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/client.rpt deleted file mode 100644 index 4f3a33e626..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/client.rpt +++ /dev/null @@ -1,81 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write abort -read aborted -read notify FIRST_ABORTED - - -connect await FIRST_ABORTED - "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x00] # flags = non clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x01] # flags = session present - [0x00] # reason code - [0x00] # properties = none - - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/server.rpt deleted file mode 100644 index f7f7e80abd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/server.rpt +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read aborted -write abort - - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x00] # flags = non clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x01] # flags = session present - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/client.rpt deleted file mode 100644 index 79b4e0b5f8..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/client.rpt +++ /dev/null @@ -1,85 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write notify FIRST_CONNECTED - -read [0xe0 0x02] # DISCONNECT - [0x8e] # session taken over - [0x00] # properties = none - -read closed -write close - -connect await FIRST_CONNECTED - "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x00] # flags = non clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x01] # flags = session present - [0x00] # reason code - [0x00] # properties = none - - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/server.rpt deleted file mode 100644 index cd44145bc9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/server.rpt +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xe0 0x02] # DISCONNECT - [0x8e] # session taken over - [0x00] # properties = none - -write close -read closed - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x00] # flags = non clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x01] # flags = session present - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/client.rpt deleted file mode 100644 index 48cba5d50c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/client.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - option zilla:byteorder "network" - -connected - -write [0x10 0x10] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x00] # flags = none - [0x00 0x3c] # keep alive = 60s - [0x05] # properties - [0x11] 1 # session expiry interval - [0x00 0x03] "one" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/server.rpt deleted file mode 100644 index 4fddefb67b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/server.rpt +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x10] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x00] # flags = none - [0x00 0x3c] # keep alive = 60s - [0x05] # properties - [0x11] 1 # session expiry interval - [0x00 0x03] "one" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/client.rpt deleted file mode 100644 index 98523cb372..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/client.rpt +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write notify FIRST_CONNECTED - -read [0xe0 0x02] # DISCONNECT - [0x8e] # session taken over - [0x00] # properties = none - -read closed -write close - - -connect await FIRST_CONNECTED - "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/server.rpt deleted file mode 100644 index 5b74a727f1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/server.rpt +++ /dev/null @@ -1,72 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xe0 0x02] # DISCONNECT - [0x8e] # session taken over - [0x00] # properties = none - -write close -read closed - - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/client.rpt deleted file mode 100644 index c6cab05d5b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/client.rpt +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x30 0x16] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x02] # properties - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/server.rpt deleted file mode 100644 index 47b29b72b7..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/server.rpt +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x30 0x16] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x02] # properties - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/client.rpt deleted file mode 100644 index 84851d383e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write notify SUBSCRIBED \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/server.rpt deleted file mode 100644 index 58b8788cba..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/client.rpt deleted file mode 100644 index de97a2a227..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/client.rpt +++ /dev/null @@ -1,73 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -write [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x02] # packet id = 2 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -write [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x03] # packet id = 3 - [0x00] # properties = none - [0x00 0x0a] "sensor/two" # topic filter - -write notify UNSUBSCRIBE_ALL_FILTERS - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason code - -read [0xb0 0x04] # UNSUBACK - [0x00 0x02] # packet id = 2 - [0x00] # properties = none - [0x00] # unsubscribe = success - -read [0xb0 0x04] # UNSUBACK - [0x00 0x03] # packet id = 3 - [0x00] # properties = none - [0x00] # unsubscribe = success - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/server.rpt deleted file mode 100644 index 9c7d67d158..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/server.rpt +++ /dev/null @@ -1,72 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -read [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x02] # packet id = 2 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -read [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x03] # packet id = 3 - [0x00] # properties = none - [0x00 0x0a] "sensor/two" # topic filter - - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason code - -write [0xb0 0x04] # UNSUBACK - [0x00 0x02] # packet id = 2 - [0x00] # properties = none - [0x00] # unsubscribe = success - -write [0xb0 0x04] # UNSUBACK - [0x00 0x03] # packet id = 3 - [0x00] # properties = none - [0x00] # unsubscribe = success diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/client.rpt deleted file mode 100644 index 75cec60eb5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/client.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 2 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -read [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 2 - [0x00] # properties = none - [0x00] # unsubscribe = success diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/server.rpt deleted file mode 100644 index 5369662547..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/server.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 2 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -write [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 2 - [0x00] # properties = none - [0x00] # unsubscribe = success diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/client.rpt deleted file mode 100644 index 7b82dfc026..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/client.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x06] # flags = will flag, clean start - [0x00 0x0a] # keep alive = 10s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0xe0 0x02] # DISCONNECT - [0x04] # disconnect with will message - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/server.rpt deleted file mode 100644 index c4e6b53855..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x06] # flags = will flag, clean start - [0x00 0x0a] # keep alive = 10s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0xe0 0x02] # DISCONNECT - [0x04] # disconnect with will message - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/client.rpt deleted file mode 100644 index 002f06c76a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x06] # flags = will flag, clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0xe0 0x02] # DISCONNECT - [0x8d] # reason = keep alive timeout - [0x00] # properties = none - -read closed -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/server.rpt deleted file mode 100644 index 25c88efa05..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x06] # flags = will flag, clean start - [0x00 0x01] # keep alive = 1s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0xe0 0x02] # DISCONNECT - [0x8d] # reason = keep alive timeout - [0x00] # properties = none - -write close -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/client.rpt deleted file mode 100644 index 5b9b318d90..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/client.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x06] # flags = will flag, clean start - [0x00 0x0a] # keep alive = 10s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0xe0 0x02] # DISCONNECT - [0x00] # normal disconnect - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/server.rpt deleted file mode 100644 index 883cc65b8e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x06] # flags = will flag, clean start - [0x00 0x0a] # keep alive = 10s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0xe0 0x02] # DISCONNECT - [0x00] # normal disconnect - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/client.rpt deleted file mode 100644 index 4059848eac..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/client.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x26] # flags = will retain, will flag, clean start - [0x00 0x0a] # keep alive = 10s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/server.rpt deleted file mode 100644 index 9114402158..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/server.rpt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x3a] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x26] # flags = will retain, will flag, clean start - [0x00 0x0a] # keep alive = 10s - [0x00] # properties - [0x00 0x03] "one" # client id - [0x02] # will properties - [0x01 0x01] # format = utf-8 - [0x00 0x09] "wills/one" # will topic - [0x00 0x1a] "client one session expired" # will payload - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/client.rpt deleted file mode 100644 index 6e205f28f4..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/client.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/server.rpt deleted file mode 100644 index 1bec59b7a5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/server.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/client.rpt deleted file mode 100644 index f7fda12388..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x83 0x12] # malformed SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0xe0 0x02] # disconnect = normal - [0x81] # malformed packet - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/server.rpt deleted file mode 100644 index d2539d4a04..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x83 0x12] # malformed SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0xe0 0x02] # disconnect = normal - [0x81] # malformed packet - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/client.rpt deleted file mode 100644 index f4689b5087..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0c] "#/sensor/one" # invalid topic filter - [0x00] # options = at-most-once, send retained - -read [0xe0 0x02] # disconnect = normal - [0x82] # protocol error - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/server.rpt deleted file mode 100644 index d19ea3313a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0c] "#/sensor/one" # invalid topic filter - [0x00] # options = at-most-once, send retained - -write [0xe0 0x02] # disconnect = normal - [0x82] # protocol error - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt deleted file mode 100644 index 394ce449c2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x3b] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x27] # properties - [0x0b 0x01] # subscription id = 1 - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt deleted file mode 100644 index 2a00fd6d2d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x3b] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x27] # properties - [0x0b 0x01] # subscription id = 1 - [0x02] 0x0f # expiry = 15 seconds - [0x03 0x00 0x07] "message" # content type - [0x01 0x01] # format = utf-8 - [0x08 0x00 0x0a] "sensor/one" # response topic - [0x09 0x00 0x04] "info" # correlation data - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/client.rpt deleted file mode 100644 index bd5b56bd3e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/client.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x2c] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x18] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "1" # user property value - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "2" # user property value - "message" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/server.rpt deleted file mode 100644 index 1613f1c5c9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/server.rpt +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x2c] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x18] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "1" # user property value - [0x26] # user property id - [0x00 0x04] "row1" # user property key - [0x00 0x01] "2" # user property value - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/client.rpt deleted file mode 100644 index 54d4a929ea..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/client.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x00] # invalid subscriptionId = 0 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0xe0 0x02] # DISCONNECT = normal - [0x82] # protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/server.rpt deleted file mode 100644 index fd237bf7b4..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/server.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x00] # invalid subscriptionId = 0 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0xe0 0x02] # DISCONNECT = normal - [0x82] # protocol error - [0x00] # properties = none - -write close # close network connection diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/client.rpt deleted file mode 100644 index 88223c46a2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/client.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/server.rpt deleted file mode 100644 index 1bec59b7a5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/server.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/client.rpt deleted file mode 100644 index e19108cb1e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/client.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x04] # options = at-most-once, no-local, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x16] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x02] # properties - [0x01 0x01] # format = utf-8 - "message" # payload - -read [0x30 0x19] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message2" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/server.rpt deleted file mode 100644 index 739316e46a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/server.rpt +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x04] # options = at-most-once, no-local, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x16] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x02] # properties - [0x01 0x01] # format = utf-8 - "message" # payload - -write [0x30 0x19] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message2" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/client.rpt deleted file mode 100644 index 20ffd331c2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/client.rpt +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client2" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x14] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message" # payload - -write notify PUBLISHED - -connect await PUBLISHED - "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client1" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x20] # options = at-most-once, do not send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/server.rpt deleted file mode 100644 index dc1c3a6e66..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/server.rpt +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client2" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x14] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message" # payload - - - -accepted -connected - -read [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client1" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x20] # options = at-most-once, do not send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/client.rpt deleted file mode 100644 index 6e3a8ee494..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/client.rpt +++ /dev/null @@ -1,83 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client1" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x31 0x14] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message" # payload - -write notify RETAINED_PUBLISHED - - -connect await RETAINED_PUBLISHED - "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client2" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/server.rpt deleted file mode 100644 index 627d0b1f62..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/server.rpt +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client1" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x31 0x14] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x00] # properties - "message" # payload - -accepted -connected - -read [0x10 0x14] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x07] "client2" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/client.rpt deleted file mode 100644 index d18dc1cf0d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/client.rpt +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/+/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x0a] "sensor/+/1" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x1c] # PUBLISH - [0x00 0x0c] "sensor/one/1" # topic name - [0x06] # properties - [0x0b 0x01] # subscription id = 1 - [0x0b 0x02] # subscription id = 2 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/server.rpt deleted file mode 100644 index 72fe7b721d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/server.rpt +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/+/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x0a] "sensor/+/1" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x1c] # PUBLISH - [0x00 0x0c] "sensor/one/1" # topic name - [0x06] # properties - [0x0b 0x01] # subscription id = 1 - [0x0b 0x02] # subscription id = 2 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/client.rpt deleted file mode 100644 index 0e3d83a2f3..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/client.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/+" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/server.rpt deleted file mode 100644 index a333bf4451..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/server.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/+" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/client.rpt deleted file mode 100644 index 5502124a84..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/client.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x30 0x16] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x02] # properties - [0x01 0x01] # format = utf-8 - "message" # payload - -read [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/server.rpt deleted file mode 100644 index 05cab126e9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/server.rpt +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x30 0x16] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x02] # properties - [0x01 0x01] # format = utf-8 - "message" # payload - -write [0x30 0x18] # PUBLISH - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/client.rpt deleted file mode 100644 index b39b697ee0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/client.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x07] # options = malformed - -read [0xe0 0x02] # DISCONNECT - [0x81] # malformed packet - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/server.rpt deleted file mode 100644 index fc394dde50..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/server.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x07] # options = malformed - -write [0xe0 0x02] # DISCONNECT - [0x81] # malformed packet - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/client.rpt deleted file mode 100644 index 683ce043d8..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x10] # SUBSCRIBE - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/server.rpt deleted file mode 100644 index 157566c112..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x10] # SUBSCRIBE - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/client.rpt deleted file mode 100644 index 9c36998f8a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/client.rpt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x03] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - -read [0xe0 0x02] # DISCONNECT - [0x00] # properties = none - [0x82] # reason = protocol error - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/server.rpt deleted file mode 100644 index 95e8e7aa4f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/server.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x03] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - -write [0xe0 0x02] # SUBACK - [0x00] # properties = none - [0x82] # reason code - -write close # close network connection diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/client.rpt deleted file mode 100644 index 41e3ba9b00..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/client.rpt +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x04] # options = at-most-once, send retained, no local - -read [0xe0 0x02] # DISCONNECT - [0x82] # protocol error - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/server.rpt deleted file mode 100644 index cbb98d694a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/server.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x04] # options = at-most-once, send retained, no local - -write [0xe0 0x02] # DISCONNECT - [0x82] # protocol error - [0x00] # properties = none diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/client.rpt deleted file mode 100644 index 089f74870e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x2a 0x00] # shared subscription unavailable - -write [0x82 0x23] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "$share/consumer1/sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0xe0 0x02] # DISCONNECT - [0x9e] # shared subscription unavailable - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/server.rpt deleted file mode 100644 index 6208375089..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x2a 0x00] # shared subscription unavailable - -read [0x82 0x23] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "$share/consumer1/sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0xe0 0x02] # DISCONNECT - [0x9e] # shared subscription unavailable - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/client.rpt deleted file mode 100644 index fcf5bf68a9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x29 0x00] # subscription identifiers unavailable - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0xe0 0x02] # DISCONNECT - [0xa1] # subscription identifiers unavailable - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/server.rpt deleted file mode 100644 index 0a49b964f9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x29 0x00] # subscription identifiers unavailable - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0xe0 0x02] # DISCONNECT - [0xa1] # subscription identifiers unavailable - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/client.rpt deleted file mode 100644 index 43385085a0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#/1" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x8f] # reason code = topic filter invalid diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/server.rpt deleted file mode 100644 index 097955c349..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#/1" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x8f] # reason code = topic filter invalid diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt deleted file mode 100644 index feedd243e0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x28 0x00] # wildcard subscription unavailable - -write [0x82 0x14] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0c] "sensor/one/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0xe0 0x02] # DISCONNECT - [0xa2] # wildcard subscription unavailable - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt deleted file mode 100644 index 74cfb47054..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x05] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x02] # properties - [0x28 0x00] # wildcard subscription unavailable - -read [0x82 0x14] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0c] "sensor/one/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0xe0 0x02] # DISCONNECT - [0xa2] # wildcard subscription unavailable - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/client.rpt deleted file mode 100644 index fa8fce65d0..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/client.rpt +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x08] # options = at-most-once, retain as published - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x31 0x18] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/server.rpt deleted file mode 100644 index 36109c91be..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/server.rpt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x08] # options = at-most-once, retain as published - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x31 0x18] # PUBLISH flags = at-most-once, retain - [0x00 0x0a] "sensor/one" # topic name - [0x04] # properties - [0x0b 0x01] # subscription id = 1 - [0x01 0x01] # format = utf-8 - "message" # payload \ No newline at end of file diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/client.rpt deleted file mode 100644 index 762c45c1de..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/server.rpt deleted file mode 100644 index 71546b1de6..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt deleted file mode 100644 index f1deb49e87..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x14] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0c] "sensor/+/1/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt deleted file mode 100644 index d0c8845cf9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x14] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0c] "sensor/+/1/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/client.rpt deleted file mode 100644 index 27336b9784..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/server.rpt deleted file mode 100644 index 81d4472629..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/client.rpt deleted file mode 100644 index 22287a377a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/+" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/server.rpt deleted file mode 100644 index d72aec3064..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/+" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/client.rpt deleted file mode 100644 index 6ebcc04bef..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/client.rpt +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/+/+" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/server.rpt deleted file mode 100644 index 8cb126d8e6..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/server.rpt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/+/+" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/client.rpt deleted file mode 100644 index 1cb03ec6a7..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/server.rpt deleted file mode 100644 index c752a811da..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt deleted file mode 100644 index d4dfa5c059..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1d] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt deleted file mode 100644 index 49467e2d2d..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1d] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -[0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/client.rpt deleted file mode 100644 index caacba76e9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1b] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/server.rpt deleted file mode 100644 index 92936e78f2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1b] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#" # topic filter - [0x00] # options = at-most-once, send retained - -[0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/client.rpt deleted file mode 100644 index 60cbbd058f..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/client.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/server.rpt deleted file mode 100644 index b53d46ff87..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/server.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/client.rpt deleted file mode 100644 index 67911e11f7..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/client.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/server.rpt deleted file mode 100644 index 37c9e42ca9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/server.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x08] "sensor/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt deleted file mode 100644 index 2fefc2f6af..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt deleted file mode 100644 index 307ca61c67..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0x82 0x10] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x02] # subscription id = 2 - [0x00 0x08] "device/#" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/client.rpt deleted file mode 100644 index 713e5e3943..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/client.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/+/#" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/+/1" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/server.rpt deleted file mode 100644 index 399d3c5e9b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/server.rpt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/+/#" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/+/1" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/client.rpt deleted file mode 100644 index db8f57700e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/client.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -read [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # unsubscribe = success diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/server.rpt deleted file mode 100644 index 61f0e8c32b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/server.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -write [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # unsubscribe = success diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/client.rpt deleted file mode 100644 index 0dc3b7a5dd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/client.rpt +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason code - -write [0xa2 0x1b] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - [0x00 0x0a] "sensor/two" # topic filter - -read [0xb0 0x05] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/server.rpt deleted file mode 100644 index 333e6686d9..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/server.rpt +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes - - -read [0xa2 0x1b] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - [0x00 0x0a] "sensor/two" # topic filter - -write [0xb0 0x05] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/client.rpt deleted file mode 100644 index 8726af2b96..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/client.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xa2 0x11] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0c] "not-matching" # topic filter - -read [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x11] # unsubscribe = no subscription existed - - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/server.rpt deleted file mode 100644 index dc53b38f52..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0xa2 0x11] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0c] "not-matching" # topic filter - -write [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x11] # unsubscribe = no subscription existed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/client.rpt deleted file mode 100644 index 6f262f1b0b..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/client.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "not-matching" # topic filter - -read [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x11] # unsubscribe = no subscription existed - - diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/server.rpt deleted file mode 100644 index cb38265c2e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/server.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "not-matching" # topic filter - -write [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x11] # unsubscribe = no subscription existed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/client.rpt deleted file mode 100644 index 6bc2fb4be1..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/client.rpt +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason code - -write [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - [0x30 0x14] # PUBLISH - [0x00 0x0a] "sensor/two" # topic name - [0x00] # properties - "message" # payload - -read [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/server.rpt deleted file mode 100644 index 1b2efb52bd..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/server.rpt +++ /dev/null @@ -1,66 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes - - -read [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - [0x30 0x14] # PUBLISH - [0x00 0x0a] "sensor/two" # topic name - [0x00] # properties - "message" # payload - -write [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/client.rpt deleted file mode 100644 index dab4e2272c..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/client.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xa3 0x0f] # malformed UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -read [0xe0 0x02] # disconnect = normal - [0x81] # malformed packet - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/server.rpt deleted file mode 100644 index 38e3d3f3e5..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/server.rpt +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0xa3 0x0f] # malformed UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -write [0xe0 0x02] # disconnect = normal - [0x81] # malformed packet - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/client.rpt deleted file mode 100644 index ff12eac7d2..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/client.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xa2 0x0d] # UNSUBSCRIBE - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -read [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/server.rpt deleted file mode 100644 index b595bf3dba..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/server.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0xa2 0x0d] # UNSUBSCRIBE - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -write [0xe0 0x02] # disconnect header - [0x82] # disconnect = protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/client.rpt deleted file mode 100644 index 38dd5dcf14..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/client.rpt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -write [0xa2 0x03] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - -read [0xe0 0x02] # DISCONNECT - [0x82] # protocol error - [0x00] # properties = none - -read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/server.rpt deleted file mode 100644 index 390f7b216e..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/server.rpt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3C] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x12] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x04] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason code - -read [0xa2 0x03] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - -write [0xe0 0x02] # DISCONNECT - [0x82] # protocol error - [0x00] # properties = none - -write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/client.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/client.rpt deleted file mode 100644 index 8347000999..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/client.rpt +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -connect "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -connected - -write [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -read [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -write [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -read [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason code - -write [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -read [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/server.rpt b/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/server.rpt deleted file mode 100644 index 670278c91a..0000000000 --- a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/server.rpt +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc. -# -# Aklivity licenses this file to you under the Apache License, -# version 2.0 (the "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -accept "zilla://streams/net0" - option zilla:window 8192 - option zilla:transmission "duplex" - option zilla:byteorder "network" - -accepted -connected - -read [0x10 0x13] # CONNECT - [0x00 0x04] "MQTT" # protocol name - [0x05] # protocol version - [0x02] # flags = clean start - [0x00 0x3c] # keep alive = 60s - [0x00] # properties = none - [0x00 0x06] "client" # client id - -write [0x20 0x03] # CONNACK - [0x00] # flags = none - [0x00] # reason code - [0x00] # properties = none - -read [0x82 0x1f] # SUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x02] # properties - [0x0b 0x01] # subscription id = 1 - [0x00 0x0a] "sensor/one" # topic filter - [0x00] # options = at-most-once, send retained - - [0x00 0x0a] "sensor/two" # topic filter - [0x00] # options = at-most-once, send retained - -write [0x90 0x05] # SUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x00] # reason codes - - -read [0xa2 0x0f] # UNSUBSCRIBE - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00 0x0a] "sensor/one" # topic filter - -write [0xb0 0x04] # UNSUBACK - [0x00 0x01] # packet id = 1 - [0x00] # properties = none - [0x00] # reason codes diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/config/SchemaTest.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/config/SchemaTest.java deleted file mode 100644 index 6541665d98..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/config/SchemaTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.config; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; - -import jakarta.json.JsonObject; - -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; - -import io.aklivity.zilla.specs.engine.config.ConfigSchemaRule; - -public class SchemaTest -{ - @Rule - public final ConfigSchemaRule schema = new ConfigSchemaRule() - .schemaPatch("io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json") - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config"); - - @Ignore("TODO") - @Test - public void shouldValidateClient() - { - JsonObject config = schema.validate("client.yaml"); - - assertThat(config, not(nullValue())); - } - - @Ignore("TODO") - @Test - public void shouldValidateClientWhenTopic() - { - JsonObject config = schema.validate("client.when.topic.yaml"); - - assertThat(config, not(nullValue())); - } - - @Ignore("TODO") - @Test - public void shouldValidateClientWhenTopicOrSessions() - { - JsonObject config = schema.validate("client.when.topic.or.sessions.yaml"); - - assertThat(config, not(nullValue())); - } - - @Ignore("TODO") - @Test - public void shouldValidateClientWhenTopicPublishOnly() - { - JsonObject config = schema.validate("client.when.topic.publish.only.yaml"); - - assertThat(config, not(nullValue())); - } - - @Ignore("TODO") - @Test - public void shouldValidateClientWhenTopicSubscribeOnly() - { - JsonObject config = schema.validate("client.when.topic.subscribe.only.yaml"); - - assertThat(config, not(nullValue())); - } - - @Test - public void shouldValidateServer() - { - JsonObject config = schema.validate("server.yaml"); - - assertThat(config, not(nullValue())); - } - - @Test - public void shouldValidateServerWhenTopic() - { - JsonObject config = schema.validate("server.when.topic.yaml"); - - assertThat(config, not(nullValue())); - } - - @Test - public void shouldValidateServerWhenTopicOrSessions() - { - JsonObject config = schema.validate("server.when.sessions.yaml"); - - assertThat(config, not(nullValue())); - } - - @Test - public void shouldValidateServerWhenTopicPublishOnly() - { - JsonObject config = schema.validate("server.when.topic.publish.only.yaml"); - - assertThat(config, not(nullValue())); - } - - @Test - public void shouldValidateServerWhenTopicSubscribeOnly() - { - JsonObject config = schema.validate("server.when.topic.subscribe.only.yaml"); - - assertThat(config, not(nullValue())); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/ConnectionIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/ConnectionIT.java deleted file mode 100644 index 34ac95860e..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/ConnectionIT.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.application; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class ConnectionIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${app}/client.sent.abort/client", - "${app}/client.sent.abort/server"}) - public void shouldReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/connect.max.packet.size.exceeded/client", - "${app}/connect.max.packet.size.exceeded/server"}) - public void shouldNotReceivePublishPacketExceedingMaxPacketLimit() throws Exception - { - k3po.finish(); - } - -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java deleted file mode 100644 index fb7ba4b644..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.application; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class PublishIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${app}/publish.one.message/client", - "${app}/publish.one.message/server"}) - public void shouldSendOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.one.message.subscribe.unfragmented/client", - "${app}/publish.one.message.subscribe.unfragmented/server"}) - public void shouldSendOneMessageSubscribeUnfragmented() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.multiple.messages/client", - "${app}/publish.multiple.messages/server"}) - public void shouldSendMultipleMessages() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.with.user.property/client", - "${app}/publish.with.user.property/server"}) - public void shouldSendWithUserProperty() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.with.user.properties.repeated/client", - "${app}/publish.with.user.properties.repeated/server"}) - public void shouldSendWithRepeatedUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.with.user.properties.distinct/client", - "${app}/publish.with.user.properties.distinct/server"}) - public void shouldSendWithDistinctUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.message.with.topic.alias/client", - "${app}/publish.message.with.topic.alias/server"}) - public void shouldSendMessageWithTopicAlias() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.messages.with.topic.alias.distinct/client", - "${app}/publish.messages.with.topic.alias.distinct/server"}) - public void shouldSendMessagesWithTopicAliasDistinct() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.messages.with.topic.alias.repeated/client", - "${app}/publish.messages.with.topic.alias.repeated/server"}) - public void shouldSendMessagesWithTopicAliasRepeated() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.messages.with.topic.alias.replaced/client", - "${app}/publish.messages.with.topic.alias.replaced/server"}) - public void shouldSendMessagesWithTopicAliasesReplaced() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.3.2-7] - @Test - @Specification({ - "${app}/publish.messages.with.topic.alias.invalid.scope/client", - "${app}/publish.messages.with.topic.alias.invalid.scope/server"}) - public void shouldSendMessagesWithTopicAliasInvalidScope() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.retained/client", - "${app}/publish.retained/server"}) - public void shouldSendRetainedMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.empty.retained.message/client", - "${app}/publish.empty.retained.message/server"}) - public void shouldSendEmptyRetainedMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/publish.empty.message/client", - "${app}/publish.empty.message/server"}) - public void shouldSendEmptyMessage() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SessionIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SessionIT.java deleted file mode 100644 index 51f6e7030b..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SessionIT.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.application; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class SessionIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - - @Test - @Specification({ - "${app}/session.connect.with.session.expiry/client", - "${app}/session.connect.with.session.expiry/server"}) - public void shouldConnectWithSessionExpiry() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.exists.clean.start/client", - "${app}/session.exists.clean.start/server"}) - public void shouldRemoveSessionAtCleanStart() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.will.message.disconnect.with.will.message/client", - "${app}/session.will.message.disconnect.with.will.message/server"}) - public void shouldSendReasonForEndAfterDisconnectWithWillMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.will.message.no.ping.within.keep.alive/client", - "${app}/session.will.message.no.ping.within.keep.alive/server"}) - public void shouldSendReasonForEndAfterKeepAliveTimeout() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.will.message.normal.disconnect/client", - "${app}/session.will.message.normal.disconnect/server"}) - public void shouldSendReasonForEndAfterNormalClientDisconnect() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.subscribe/client", - "${app}/session.subscribe/server"}) - public void shouldSubscribeSaveSubscriptionsInSession() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-15] - @Test - @Specification({ - "${app}/session.will.message.retain/client", - "${app}/session.will.message.retain/server"}) - public void shouldConnectWithWillMessageWithRetain() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.abort.reconnect.non.clean.start/client", - "${app}/session.abort.reconnect.non.clean.start/server"}) - public void shouldReconnectNonCleanStart() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.client.takeover/client", - "${app}/session.client.takeover/server"}) - public void shouldTakeOverSession() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.unsubscribe.after.subscribe/client", - "${app}/session.unsubscribe.after.subscribe/server"}) - public void shouldUnsubscribeAndUpdateSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.subscribe.via.session.state/client", - "${app}/session.subscribe.via.session.state/server"}) - public void shouldReceiveMessageSubscribedViaSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.unsubscribe.via.session.state/client", - "${app}/session.unsubscribe.via.session.state/server"}) - public void shouldUnsubscribeViaSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/session.unsubscribe.after.subscribe.deferred/client", - "${app}/session.unsubscribe.after.subscribe.deferred/server"}) - public void shouldUnsubscribeAfterSubscribeDeferred() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SubscribeIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SubscribeIT.java deleted file mode 100644 index d4e77f92a8..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SubscribeIT.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.application; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class SubscribeIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${app}/subscribe.topic.filter.single.exact/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - public void shouldFilterExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filter.multi.level.wildcard/client", - "${app}/subscribe.topic.filter.multi.level.wildcard/server"}) - public void shouldFilterMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filter.single.level.wildcard/client", - "${app}/subscribe.topic.filter.single.level.wildcard/server"}) - public void shouldFilterSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filter.single.and.multi.level.wildcard/client", - "${app}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) - public void shouldFilterSingleAndMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filter.two.single.level.wildcard/client", - "${app}/subscribe.topic.filter.two.single.level.wildcard/server"}) - public void shouldFilterTwoSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filters.aggregated.both.exact/client", - "${app}/subscribe.topic.filters.aggregated.both.exact/server"}) - public void shouldFilterAggregatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filters.isolated.both.exact/client", - "${app}/subscribe.topic.filters.isolated.both.exact/server"}) - public void shouldFilterIsolatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filters.disjoint.wildcards/client", - "${app}/subscribe.topic.filters.disjoint.wildcards/server"}) - public void shouldFilterDisjointWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filters.overlapping.wildcards/client", - "${app}/subscribe.topic.filters.overlapping.wildcards/server"}) - public void shouldFilterOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filters.isolated.both.wildcard/client", - "${app}/subscribe.topic.filters.isolated.both.wildcard/server"}) - public void shouldFilterIsolatedBothWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", - "${app}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) - public void shouldFilterAggregatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.topic.filters.isolated.exact.and.wildcard/client", - "${app}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) - public void shouldFilterIsolatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.one.message/client", - "${app}/subscribe.one.message/server"}) - public void shouldReceiveOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.one.message.user.properties.unaltered/client", - "${app}/subscribe.one.message.user.properties.unaltered/server"}) - public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.publish.no.local/client", - "${app}/subscribe.publish.no.local/server"}) - public void shouldNotReceivePublishLocal() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.receive.message/client", - "${app}/subscribe.receive.message/server"}) - public void shouldReceiveOneMessageAfterPublish() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.receive.message.wildcard/client", - "${app}/subscribe.receive.message.wildcard/server"}) - public void shouldReceiveOneMessageWithPatternTopic() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.get.retained.as.published/client", - "${app}/subscribe.get.retained.as.published/server"}) - public void shouldReceiveRetainedAsPublished() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.one.message.receive.response.topic.and.correlation.data/client", - "${app}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) - public void shouldReceiveCorrelationData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.qos0.replay.retained.no.packet.id/client", - "${app}/subscribe.qos0.replay.retained.no.packet.id/server"}) - public void shouldReceiveAndReplayRetainedQos0() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/subscribe.qos0.publish.retained.no.replay/client", - "${app}/subscribe.qos0.publish.retained.no.replay/server"}) - public void shouldNotReplayRetained() throws Exception - { - k3po.finish(); - } - -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/UnsubscribeIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/UnsubscribeIT.java deleted file mode 100644 index 3d8e13e535..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/UnsubscribeIT.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.application; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class UnsubscribeIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${app}/unsubscribe.after.subscribe/client", - "${app}/unsubscribe.after.subscribe/server"}) - public void shouldAcknowledge() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/unsubscribe.aggregated.topic.filters.both.exact/client", - "${app}/unsubscribe.aggregated.topic.filters.both.exact/server"}) - public void shouldAcknowledgeAggregatedTopicFiltersBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/unsubscribe.topic.filter.single/client", - "${app}/unsubscribe.topic.filter.single/server"}) - public void shouldAcknowledgeSingleTopicFilters() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${app}/unsubscribe.publish.unfragmented/client", - "${app}/unsubscribe.publish.unfragmented/server"}) - public void shouldAcknowledgeAndPublishUnfragmented() throws Exception - { - k3po.finish(); - } - -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/ConnectionIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/ConnectionIT.java deleted file mode 100644 index 4dcacde78a..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/ConnectionIT.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.network; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class ConnectionIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${net}/connect.successful/client", - "${net}/connect.successful/server"}) - public void shouldConnect() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.server.assigned.client.id/client", - "${net}/connect.server.assigned.client.id/server"}) - public void shouldConnectWithServerAssignedClientId() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.reject.missing.client.id/client", - "${net}/connect.reject.missing.client.id/server"}) - public void shouldRejectMissingClientId() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/disconnect/client", - "${net}/disconnect/server"}) - public void shouldConnectThenDisconnect() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.invalid.protocol.version/client", - "${net}/connect.invalid.protocol.version/server"}) - public void shouldRejectInvalidProtocolVersion() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.invalid.flags/client", - "${net}/connect.invalid.flags/server"}) - public void shouldRejectMalformedConnectPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.invalid.authentication.method/client", - "${net}/connect.invalid.authentication.method/server"}) - public void shouldRejectBadAuthenticationMethod() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/disconnect.reject.invalid.fixed.header.flags/client", - "${net}/disconnect.reject.invalid.fixed.header.flags/server"}) - public void shouldRejectMalformedDisconnectPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.reject.second.connect/client", - "${net}/connect.reject.second.connect/server"}) - public void shouldRejectSecondConnectPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.reject.topic.alias.maximum.repeated/client", - "${net}/connect.reject.topic.alias.maximum.repeated/server"}) - public void shouldRejectConnectWhenTopicAliasMaximumRepeated() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.successful.fragmented/client", - "${net}/connect.successful.fragmented/server"}) - public void shouldConnectFragmented() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.0-1] - @Test - @Specification({ - "${net}/connect.reject.other.packet.before.connect/client", - "${net}/connect.reject.other.packet.before.connect/server"}) - public void shouldRejectOtherPacketBeforeConnect() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/client.sent.close/client", - "${net}/client.sent.close/server"}) - public void shouldReceiveClientSentClose() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/client.sent.abort/client", - "${net}/client.sent.abort/server"}) - public void shouldReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/client.sent.reset/client", - "${net}/client.sent.reset/server"}) - public void shouldReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/disconnect.after.keep.alive.timeout/client", - "${net}/disconnect.after.keep.alive.timeout/server"}) - public void shouldDisconnectClientAfterKeepAliveTimeout() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-21], [MQTT-3.2.2-21] - @Test - @Specification({ - "${net}/connect.server.defined.keep.alive/client", - "${net}/connect.server.defined.keep.alive/server"}) - public void shouldConnectAndUseServerDefinedKeepAlive() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.timeout.before.connect/client", - "${net}/connect.timeout.before.connect/server"}) - public void shouldTimeoutBeforeConnect() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.maximum.qos.0/client", - "${net}/connect.maximum.qos.0/server"}) - public void shouldConnectWithMaximumQos0() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.retain.not.supported/client", - "${net}/connect.retain.not.supported/server"}) - public void shouldConnectWithRetainNotSupported() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.2.2-13] - @Test - @Specification({ - "${net}/connect.reject.will.retain.not.supported/client", - "${net}/connect.reject.will.retain.not.supported/server"}) - public void shouldRejectConnectWillRetainNotSupported() throws Exception - { - k3po.finish(); - } - - @Ignore - @Test - @Specification({ - "${net}/connect.reject.username.not.authorized/client", - "${net}/connect.reject.username.not.authorized/server"}) - public void shouldRejectConnectWithUsernameNotAuthorized() throws Exception - { - k3po.finish(); - } - - @Ignore - @Test - @Specification({ - "${net}/connect.reject.password.not.authorized/client", - "${net}/connect.reject.password.not.authorized/server"}) - public void shouldRejectConnectWithPasswordNotAuthorized() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.will.invalid.will.qos/client", - "${net}/connect.will.invalid.will.qos/server"}) - public void shouldRejectInvalidWillQos() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.will.reject.will.qos.1.without.will.flag/client", - "${net}/connect.will.reject.will.qos.1.without.will.flag/server"}) - public void shouldRejectWillQos1WithoutWillFlag() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.will.reject.will.qos.2.without.will.flag/client", - "${net}/connect.will.reject.will.qos.2.without.will.flag/server"}) - public void shouldRejectWillQos2WithoutWillFlag() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.will.reject.will.retain.without.will.flag/client", - "${net}/connect.will.reject.will.retain.without.will.flag/server"}) - public void shouldRejectWillRetainWithoutWillFlag() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-9] - @Test - @Specification({ - "${net}/connect.reject.will.payload.missing/client", - "${net}/connect.reject.will.payload.missing/server"}) - public void shouldRejectConnectWillPayloadMissing() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-9] - @Test - @Specification({ - "${net}/connect.reject.will.properties.missing/client", - "${net}/connect.reject.will.properties.missing/server"}) - public void shouldRejectConnectWillPropertiesMissing() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-9] - @Test - @Specification({ - "${net}/connect.reject.will.topic.missing/client", - "${net}/connect.reject.will.topic.missing/server"}) - public void shouldRejectConnectWillTopicNotMissing() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-16] - @Test - @Specification({ - "${net}/connect.reject.username.flag.missing/client", - "${net}/connect.reject.username.flag.missing/server"}) - public void shouldRejectUsernameUserFlagMissing() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-18] - @Test - @Specification({ - "${net}/connect.reject.password.no.password.flag/client", - "${net}/connect.reject.password.no.password.flag/server"}) - public void shouldRejectPasswordWhenMissingPasswordFlag() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-17] - @Test - @Specification({ - "${net}/connect.reject.username.flag.only/client", - "${net}/connect.reject.username.flag.only/server"}) - public void shouldRejectConnectUsernameFlagOnly() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-19] - @Test - @Specification({ - "${net}/connect.reject.password.flag.no.password/client", - "${net}/connect.reject.password.flag.no.password/server"}) - public void shouldRejectPasswordFlagWhenMissingPassword() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-24] - @Test - @Specification({ - "${net}/connect.max.packet.size.exceeded/client", - "${net}/connect.max.packet.size.exceeded/server"}) - public void shouldNotReceivePublishPacketExceedingMaxPacketLimit() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/connect.subscribe.unfragmented/client", - "${net}/connect.subscribe.unfragmented/server"}) - public void shouldConnectAndSubscribeUnfragmented() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PingIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PingIT.java deleted file mode 100644 index 5b35abb5ad..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PingIT.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.network; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class PingIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${net}/ping/client", - "${net}/ping/server"}) - public void shouldConnectThenPingRequestResponse() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/ping.keep.alive/client", - "${net}/ping.keep.alive/server"}) - public void shouldPingAtKeepAliveInterval() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PublishIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PublishIT.java deleted file mode 100644 index ce7c54e095..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PublishIT.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.network; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class PublishIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${net}/publish.one.message/client", - "${net}/publish.one.message/server"}) - public void shouldSendOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.multiple.messages/client", - "${net}/publish.multiple.messages/server"}) - public void shouldSendMultipleMessages() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.multiple.messages.unfragmented/client", - "${net}/publish.multiple.messages.unfragmented/server"}) - public void shouldSendMultipleMessagesUnfragmented() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.multiple.messages.with.delay/client", - "${net}/publish.multiple.messages.with.delay/server"}) - public void shouldSendMultipleMessagesWithDelay() throws Exception - { - k3po.start(); - k3po.awaitBarrier("PUBLISHED_MESSAGE_TWO"); - k3po.notifyBarrier("PUBLISH_MESSAGE_THREE"); - k3po.finish(); - } - - // [MQTT-2.2.1-2] - @Test - @Specification({ - "${net}/publish.reject.qos0.with.packet.id/client", - "${net}/publish.reject.qos0.with.packet.id/server"}) - public void shouldRejectQos0WithPackedId() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.2.2-9], [MQTT-3.2.2-12] - @Test - @Specification({ - "${net}/publish.reject.qos1.not.supported/client", - "${net}/publish.reject.qos1.not.supported/server"}) - public void shouldRejectQos1NotSupported() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.2.2-9], [MQTT-3.2.2-12] - @Test - @Specification({ - "${net}/publish.reject.qos2.not.supported/client", - "${net}/publish.reject.qos2.not.supported/server"}) - public void shouldRejectQos2NotSupported() throws Exception - { - k3po.finish(); - } - - // [MQTT-2.2.1-3] - @Test - @Specification({ - "${net}/publish.reject.qos1.without.packet.id/client", - "${net}/publish.reject.qos1.without.packet.id/server"}) - public void shouldRejectQos1WithoutPackedId() throws Exception - { - k3po.finish(); - } - - // [MQTT-2.2.1-3] - @Test - @Specification({ - "${net}/publish.reject.qos2.without.packet.id/client", - "${net}/publish.reject.qos2.without.packet.id/server"}) - public void shouldRejectQos2WithoutPackedId() throws Exception - { - k3po.finish(); - } - - // [MQTT-2.2.1-3] - @Test - @Specification({ - "${net}/publish.reject.invalid.payload.format/client", - "${net}/publish.reject.invalid.payload.format/server"}) - public void shouldRejectInvalidPayloadFormat() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.3.4-6] - @Test - @Specification({ - "${net}/publish.reject.client.sent.subscription.id/client", - "${net}/publish.reject.client.sent.subscription.id/server"}) - public void shouldRejectClientSentSubscriptionId() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.reject.topic.alias.exceeds.maximum/client", - "${net}/publish.reject.topic.alias.exceeds.maximum/server"}) - public void shouldRejectWhenTopicAliasExceedsThanMaximum() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.2.2-14] - @Test - @Specification({ - "${net}/publish.reject.retain.not.supported/client", - "${net}/publish.reject.retain.not.supported/server"}) - public void shouldRejectRetainedRetainNotSupported() throws Exception - { - k3po.finish(); - } - - - @Test - @Specification({ - "${net}/publish.reject.topic.alias.repeated/client", - "${net}/publish.reject.topic.alias.repeated/server"}) - public void shouldRejectWhenTopicAliasRepeated() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.topic.not.routed/client", - "${net}/publish.topic.not.routed/server"}) - public void shouldRejectTopicNotRouted() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.with.user.property/client", - "${net}/publish.with.user.property/server"}) - public void shouldSendWithUserProperty() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.with.user.properties.repeated/client", - "${net}/publish.with.user.properties.repeated/server"}) - public void shouldSendWithRepeatedUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.with.user.properties.distinct/client", - "${net}/publish.with.user.properties.distinct/server"}) - public void shouldSendWithDistinctUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.message.with.topic.alias/client", - "${net}/publish.message.with.topic.alias/server"}) - public void shouldSendMessageWithTopicAlias() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.messages.with.topic.alias.distinct/client", - "${net}/publish.messages.with.topic.alias.distinct/server"}) - public void shouldSendMessagesWithTopicAliasDistinct() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.messages.with.topic.alias.repeated/client", - "${net}/publish.messages.with.topic.alias.repeated/server"}) - public void shouldSendMessagesWithTopicAliasRepeated() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.messages.with.topic.alias.replaced/client", - "${net}/publish.messages.with.topic.alias.replaced/server"}) - public void shouldSendMessagesWithTopicAliasReplaced() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.3.2-7] - @Test - @Specification({ - "${net}/publish.messages.with.topic.alias.invalid.scope/client", - "${net}/publish.messages.with.topic.alias.invalid.scope/server"}) - public void shouldSendMessagesWithTopicAliasInvalidScope() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.retained/client", - "${net}/publish.retained/server"}) - public void shouldSendRetainedMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.empty.retained.message/client", - "${net}/publish.empty.retained.message/server"}) - public void shouldSendEmptyRetainedMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.empty.message/client", - "${net}/publish.empty.message/server"}) - public void shouldSendEmptyMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.publish.no.local/client", - "${net}/subscribe.publish.no.local/server"}) - public void shouldSubscribeThenSendNoLocal() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/publish.one.message.subscribe.unfragmented/client", - "${net}/publish.one.message.subscribe.unfragmented/server"}) - public void shouldPublishOneMessageThenSubscribeUnfragmented() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SessionIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SessionIT.java deleted file mode 100644 index 8f515004df..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SessionIT.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.network; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class SessionIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - - @Test - @Specification({ - "${net}/session.connect.with.session.expiry/client", - "${net}/session.connect.with.session.expiry/server"}) - public void shouldConnectWithSessionExpiry() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-5], [MQTT-3.1.2-23] - @Test - @Specification({ - "${net}/session.abort.reconnect.non.clean.start/client", - "${net}/session.abort.reconnect.non.clean.start/server"}) - public void shouldReconnectNonCleanStart() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.client.takeover/client", - "${net}/session.client.takeover/server"}) - public void shouldTakeOverSession() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.subscribe/client", - "${net}/session.subscribe/server"}) - public void shouldSubscribeSaveSubscriptionsInSession() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.will.message.disconnect.with.will.message/client", - "${net}/session.will.message.disconnect.with.will.message/server"}) - public void shouldConnectWithWillMessageThenDisconnectWithWillMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.exists.clean.start/client", - "${net}/session.exists.clean.start/server"}) - public void shouldRemoveSessionAtCleanStart() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.will.message.no.ping.within.keep.alive/client", - "${net}/session.will.message.no.ping.within.keep.alive/server"}) - public void shouldConnectWithWillMessageThenNoPingWithinKeepAlive() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.will.message.normal.disconnect/client", - "${net}/session.will.message.normal.disconnect/server"}) - public void shouldConnectWithWillMessageThenNormalDisconnect() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.2-15] - @Test - @Specification({ - "${net}/session.will.message.retain/client", - "${net}/session.will.message.retain/server"}) - public void shouldConnectWithWillMessageWithRetain() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.unsubscribe.after.subscribe/client", - "${net}/session.unsubscribe.after.subscribe/server"}) - public void shouldUnsubscribeAndUpdateSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.subscribe.via.session.state/client", - "${net}/session.subscribe.via.session.state/server"}) - public void shouldReceiveMessageSubscribedViaSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/session.unsubscribe.after.subscribe.deferred/client", - "${net}/session.unsubscribe.after.subscribe.deferred/server"}) - public void shouldUnsubscribeAfterSubscribeDeferred() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SubscribeIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SubscribeIT.java deleted file mode 100644 index 675e20f3b2..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SubscribeIT.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.network; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class SubscribeIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - @Test - @Specification({ - "${net}/subscribe.one.message/client", - "${net}/subscribe.one.message/server"}) - public void shouldReceiveOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.one.message.user.properties.unaltered/client", - "${net}/subscribe.one.message.user.properties.unaltered/server"}) - public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.receive.message.wildcard/client", - "${net}/subscribe.receive.message.wildcard/server"}) - public void shouldReceiveOneMessageWithPatternTopic() throws Exception - { - k3po.finish(); - } - - // [MQTT-2.2.1-3] - @Test - @Specification({ - "${net}/subscribe.reject.missing.packet.id/client", - "${net}/subscribe.reject.missing.packet.id/server"}) - public void shouldRejectWithoutPacketId() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.reject.missing.topic.filters/client", - "${net}/subscribe.reject.missing.topic.filters/server"}) - public void shouldRejectWithMissingTopicFilters() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.invalid.topic.filter/client", - "${net}/subscribe.invalid.topic.filter/server"}) - public void shouldRejectInvalidTopicFilter() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filter.single.exact/client", - "${net}/subscribe.topic.filter.single.exact/server"}) - public void shouldFilterExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filter.multi.level.wildcard/client", - "${net}/subscribe.topic.filter.multi.level.wildcard/server"}) - public void shouldFilterMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filter.single.level.wildcard/client", - "${net}/subscribe.topic.filter.single.level.wildcard/server"}) - public void shouldFilterSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filter.two.single.level.wildcard/client", - "${net}/subscribe.topic.filter.two.single.level.wildcard/server"}) - public void shouldFilterTwoSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filter.single.and.multi.level.wildcard/client", - "${net}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) - public void shouldFilterSingleAndMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filters.disjoint.wildcards/client", - "${net}/subscribe.topic.filters.disjoint.wildcards/server"}) - public void shouldFilterDisjointWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filters.overlapping.wildcards/client", - "${net}/subscribe.topic.filters.overlapping.wildcards/server"}) - public void shouldFilterOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - - @Test - @Specification({ - "${net}/subscribe.reject.topic.filter.invalid.wildcard/client", - "${net}/subscribe.reject.topic.filter.invalid.wildcard/server"}) - public void shouldRejectTopicFilterInvalidWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filters.aggregated.both.exact/client", - "${net}/subscribe.topic.filters.aggregated.both.exact/server"}) - public void shouldFilterAggregatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filters.isolated.both.exact/client", - "${net}/subscribe.topic.filters.isolated.both.exact/server"}) - public void shouldFilterIsolatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filters.isolated.both.wildcard/client", - "${net}/subscribe.topic.filters.isolated.both.wildcard/server"}) - public void shouldFilterIsolatedBothWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", - "${net}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) - public void shouldFilterAggregatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.topic.filters.isolated.exact.and.wildcard/client", - "${net}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) - public void shouldFilterIsolatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.invalid.fixed.header.flags/client", - "${net}/subscribe.invalid.fixed.header.flags/server"}) - public void shouldRejectMalformedPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.reject.no.local/client", - "${net}/subscribe.reject.no.local/server"}) - public void shouldRejectNoLocal() throws Exception - { - k3po.finish(); - } - - - // [MQTT-3.3.2-15], [MQTT-3.3.2-16] - @Test - @Specification({ - "${net}/subscribe.one.message.receive.response.topic.and.correlation.data/client", - "${net}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) - public void shouldReceiveCorrelationData() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.one.message.with.invalid.subscription.id/client", - "${net}/subscribe.one.message.with.invalid.subscription.id/server"}) - public void shouldReceiveOneMessageWithInvalidSubscriptionId() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.receive.message/client", - "${net}/subscribe.receive.message/server"}) - public void shouldReceiveOneMessageAfterPublish() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.get.retained.as.published/client", - "${net}/subscribe.get.retained.as.published/server"}) - public void shouldReceiveRetainedAsPublished() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.8.3-5] - @Test - @Specification({ - "${net}/subscribe.reject.malformed.subscription.options/client", - "${net}/subscribe.reject.malformed.subscription.options/server"}) - public void shouldRejectMalformedSubscriptionOptions() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.reject.wildcard.subscriptions.not.supported/client", - "${net}/subscribe.reject.wildcard.subscriptions.not.supported/server"}) - public void shouldRejectWildcardSubscriptionsNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.reject.subscription.ids.not.supported/client", - "${net}/subscribe.reject.subscription.ids.not.supported/server"}) - public void shouldRejectSubscriptionIdentifiersNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.reject.shared.subscriptions.not.supported/client", - "${net}/subscribe.reject.shared.subscriptions.not.supported/server"}) - public void shouldRejectSharedSubscriptionsNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.qos0.replay.retained.no.packet.id/client", - "${net}/subscribe.qos0.replay.retained.no.packet.id/server"}) - public void shouldReceiveAndReplayRetainedQos0() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/subscribe.qos0.publish.retained.no.replay/client", - "${net}/subscribe.qos0.publish.retained.no.replay/server"}) - public void shouldNotReplayRetained() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/UnsubscribeIT.java b/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/UnsubscribeIT.java deleted file mode 100644 index 865c0a07fc..0000000000 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/UnsubscribeIT.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.specs.binding.mqtt.streams.network; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -public class UnsubscribeIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); - - @Rule - public final TestRule chain = outerRule(k3po).around(timeout); - - // [MQTT-2.2.1-3] - @Test - @Specification({ - "${net}/unsubscribe.reject.missing.packet.id/client", - "${net}/unsubscribe.reject.missing.packet.id/server"}) - public void shouldRejectWithoutPacketId() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/unsubscribe.after.subscribe/client", - "${net}/unsubscribe.after.subscribe/server"}) - public void shouldAcknowledge() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.10.4-5] - @Test - @Specification({ - "${net}/unsubscribe.no.matching.subscription/client", - "${net}/unsubscribe.no.matching.subscription/server"}) - public void shouldAcknowledgeNoMatchingSubscription() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/unsubscribe.aggregated.topic.filters.both.exact/client", - "${net}/unsubscribe.aggregated.topic.filters.both.exact/server"}) - public void shouldAcknowledgeAggregatedTopicFiltersBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/unsubscribe.topic.filter.single/client", - "${net}/unsubscribe.topic.filter.single/server"}) - public void shouldAcknowledgeSingleTopicFilters() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.10.1-1] - @Test - @Specification({ - "${net}/unsubscribe.reject.invalid.fixed.header.flags/client", - "${net}/unsubscribe.reject.invalid.fixed.header.flags/server"}) - public void shouldRejectMalformedPacket() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.10.3-2] - @Test - @Specification({ - "${net}/unsubscribe.reject.no.topic.filter/client", - "${net}/unsubscribe.reject.no.topic.filter/server"}) - public void shouldRejectNoTopicFilter() throws Exception - { - k3po.finish(); - } - - @Test - @Specification({ - "${net}/unsubscribe.publish.unfragmented/client", - "${net}/unsubscribe.publish.unfragmented/server"}) - public void shouldAcknowledgeAndPublishUnfragmented() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt/pom.xml b/incubator/binding-mqtt/pom.xml deleted file mode 100644 index 63dffa119c..0000000000 --- a/incubator/binding-mqtt/pom.xml +++ /dev/null @@ -1,235 +0,0 @@ - - - - 4.0.0 - - io.aklivity.zilla - incubator - 0.9.51 - ../pom.xml - - - binding-mqtt - zilla::incubator::binding-mqtt - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - 11 - 11 - 0.69 - 3 - - - - - ${project.groupId} - binding-mqtt.spec - ${project.version} - provided - - - ${project.groupId} - engine - ${project.version} - provided - - - ${project.groupId} - engine - test-jar - ${project.version} - test - - - junit - junit - test - - - org.hamcrest - hamcrest-library - test - - - org.mockito - mockito-core - test - - - org.kaazing - k3po.junit - test - - - org.kaazing - k3po.lang - test - - - org.openjdk.jmh - jmh-core - test - - - org.openjdk.jmh - jmh-generator-annprocess - test - - - - - - - org.jasig.maven - maven-notice-plugin - - - ${project.groupId} - flyweight-maven-plugin - ${project.version} - - core mqtt protocol - io.aklivity.zilla.runtime.binding.mqtt.internal.types - - - - - generate - - - - - - com.mycila - license-maven-plugin - - - maven-checkstyle-plugin - - - maven-dependency-plugin - - - process-resources - - unpack - - - - - ${project.groupId} - binding-mqtt.spec - - - ^\Qio/aklivity/zilla/specs/binding/mqtt/\E - io/aklivity/zilla/runtime/binding/mqtt/internal/ - - - - - io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json - ${project.build.directory}/classes - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.moditect - moditect-maven-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - org.kaazing - k3po-maven-plugin - - - ${project.groupId} - engine - ${project.version} - test-jar - - - ${project.groupId} - engine - ${project.version} - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.jacoco - jacoco-maven-plugin - - - io/aklivity/zilla/runtime/binding/mqtt/internal/types/**/*.class - - - - BUNDLE - - - INSTRUCTION - COVEREDRATIO - ${jacoco.coverage.ratio} - - - CLASS - MISSEDCOUNT - ${jacoco.missed.count} - - - - - - - - io.gatling - maven-shade-plugin - - - - org.agrona:agrona - io.aklivity.zilla:engine - org.openjdk.jmh:jmh-core - net.sf.jopt-simple:jopt-simple - org.apache.commons:commons-math3 - commons-cli:commons-cli - com.github.biboudis:jmh-profilers - - - - - - - diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfiguration.java b/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfiguration.java deleted file mode 100644 index 36794d2dfe..0000000000 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfiguration.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal; - -import java.util.concurrent.TimeUnit; - -import io.aklivity.zilla.runtime.engine.Configuration; - -public class MqttConfiguration extends Configuration -{ - private static final ConfigurationDef MQTT_CONFIG; - public static final LongPropertyDef CONNECT_TIMEOUT; - public static final LongPropertyDef PUBLISH_TIMEOUT; - public static final IntPropertyDef SESSION_EXPIRY_INTERVAL; - public static final ShortPropertyDef KEEP_ALIVE_MINIMUM; - public static final ShortPropertyDef KEEP_ALIVE_MAXIMUM; - public static final BytePropertyDef MAXIMUM_QOS; - public static final BooleanPropertyDef RETAIN_AVAILABLE; - public static final ShortPropertyDef TOPIC_ALIAS_MAXIMUM; - public static final BooleanPropertyDef WILDCARD_SUBSCRIPTION_AVAILABLE; - public static final BooleanPropertyDef SUBSCRIPTION_IDENTIFIERS_AVAILABLE; - public static final BooleanPropertyDef SHARED_SUBSCRIPTION_AVAILABLE; - public static final BooleanPropertyDef SESSIONS_AVAILABLE; - public static final BooleanPropertyDef NO_LOCAL; - public static final IntPropertyDef SESSION_EXPIRY_GRACE_PERIOD; - public static final PropertyDef CLIENT_ID; - - static - { - final ConfigurationDef config = new ConfigurationDef("zilla.binding.mqtt"); - PUBLISH_TIMEOUT = config.property("publish.timeout", TimeUnit.SECONDS.toSeconds(30)); - CONNECT_TIMEOUT = config.property("connect.timeout", TimeUnit.SECONDS.toSeconds(3)); - SESSION_EXPIRY_INTERVAL = config.property("session.expiry.interval", Integer.MAX_VALUE); - //TODO: better default values? - KEEP_ALIVE_MINIMUM = config.property("keep.alive.minimum", (short) 10); - KEEP_ALIVE_MAXIMUM = config.property("keep.alive.maximum", (short) 1000); - MAXIMUM_QOS = config.property("maximum.qos", (byte) 0); - RETAIN_AVAILABLE = config.property("retain.available", true); - TOPIC_ALIAS_MAXIMUM = config.property("topic.alias.maximum", (short) 0); - WILDCARD_SUBSCRIPTION_AVAILABLE = config.property("wildcard.subscription.available", true); - SUBSCRIPTION_IDENTIFIERS_AVAILABLE = config.property("subscription.identifiers.available", true); - SHARED_SUBSCRIPTION_AVAILABLE = config.property("shared.subscription.available", false); - SESSIONS_AVAILABLE = config.property("sessions.available", true); - NO_LOCAL = config.property("no.local", true); - SESSION_EXPIRY_GRACE_PERIOD = config.property("session.expiry.grace.period", 30); - CLIENT_ID = config.property("client.id"); - MQTT_CONFIG = config; - } - - public MqttConfiguration( - Configuration config) - { - super(MQTT_CONFIG, config); - } - - public long publishTimeout() - { - return PUBLISH_TIMEOUT.get(this); - } - - public long connectTimeout() - { - return CONNECT_TIMEOUT.get(this); - } - - public boolean retainAvailable() - { - return RETAIN_AVAILABLE.get(this); - } - - public int sessionExpiryInterval() - { - return SESSION_EXPIRY_INTERVAL.get(this); - } - - public short keepAliveMinimum() - { - return KEEP_ALIVE_MINIMUM.get(this); - } - - public short keepAliveMaximum() - { - return KEEP_ALIVE_MAXIMUM.get(this); - } - - public byte maximumQos() - { - return MAXIMUM_QOS.get(this); - } - - public short topicAliasMaximum() - { - return TOPIC_ALIAS_MAXIMUM.get(this); - } - - public boolean wildcardSubscriptionAvailable() - { - return WILDCARD_SUBSCRIPTION_AVAILABLE.get(this); - } - - public boolean subscriptionIdentifierAvailable() - { - return SUBSCRIPTION_IDENTIFIERS_AVAILABLE.get(this); - } - - public boolean sharedSubscriptionAvailable() - { - return SHARED_SUBSCRIPTION_AVAILABLE.get(this); - } - - public boolean sessionsAvailable() - { - return SESSIONS_AVAILABLE.get(this); - } - - public boolean noLocal() - { - return NO_LOCAL.get(this); - } - - public int sessionExpiryGracePeriod() - { - return SESSION_EXPIRY_GRACE_PERIOD.get(this); - } - - public String clientId() - { - return CLIENT_ID.get(this); - } -} diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttBindingConfig.java b/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttBindingConfig.java deleted file mode 100644 index bc98037e48..0000000000 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttBindingConfig.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.config; - -import static java.util.stream.Collectors.toList; - -import java.util.List; - -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities; -import io.aklivity.zilla.runtime.engine.config.BindingConfig; -import io.aklivity.zilla.runtime.engine.config.KindConfig; - -public final class MqttBindingConfig -{ - public final long id; - public final String name; - public final KindConfig kind; - public final List routes; - - public MqttBindingConfig( - BindingConfig binding) - { - this.id = binding.id; - this.name = binding.name; - this.kind = binding.kind; - this.routes = binding.routes.stream().map(MqttRouteConfig::new).collect(toList()); - } - - public MqttRouteConfig resolve( - long authorization, - MqttCapabilities capabilities) - { - return routes.stream() - .filter(r -> r.authorized(authorization) && r.matches(capabilities)) - .findFirst() - .orElse(null); - } - - public MqttRouteConfig resolve( - long authorization, - String topic, - MqttCapabilities capabilities) - { - return routes.stream() - .filter(r -> r.authorized(authorization) && r.matches(topic, capabilities)) - .findFirst() - .orElse(null); - } -} diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfig.java b/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfig.java deleted file mode 100644 index 0492fd2190..0000000000 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.config; - -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities; -import io.aklivity.zilla.runtime.engine.config.ConditionConfig; - -public final class MqttConditionConfig extends ConditionConfig -{ - public final String topic; - public final MqttCapabilities capabilities; - - public MqttConditionConfig( - String topic, - MqttCapabilities capabilities) - { - this.topic = topic; - this.capabilities = capabilities; - } -} - diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapter.java b/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapter.java deleted file mode 100644 index 32468e6666..0000000000 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapter.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.config; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.bind.adapter.JsonbAdapter; - -import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttBinding; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities; -import io.aklivity.zilla.runtime.engine.config.ConditionConfig; -import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; - -public final class MqttConditionConfigAdapter implements ConditionConfigAdapterSpi, JsonbAdapter -{ - private static final String TOPIC_NAME = "topic"; - private static final String CAPABILITIES_NAME = "capabilities"; - - @Override - public String type() - { - return MqttBinding.NAME; - } - - @Override - public JsonObject adaptToJson( - ConditionConfig condition) - { - MqttConditionConfig mqttCondition = (MqttConditionConfig) condition; - - JsonObjectBuilder object = Json.createObjectBuilder(); - - if (mqttCondition.topic != null) - { - object.add(TOPIC_NAME, mqttCondition.topic); - } - - if (mqttCondition.capabilities != null) - { - object.add(CAPABILITIES_NAME, mqttCondition.capabilities.toString().toLowerCase()); - } - - return object.build(); - } - - @Override - public ConditionConfig adaptFromJson( - JsonObject object) - { - String topic = object.containsKey(TOPIC_NAME) - ? object.getString(TOPIC_NAME) - : null; - - MqttCapabilities capabilities = object.containsKey(CAPABILITIES_NAME) - ? MqttCapabilities.valueOf(object.getString(CAPABILITIES_NAME).toUpperCase()) - : null; - - return new MqttConditionConfig(topic, capabilities); - } -} diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionMatcher.java b/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionMatcher.java deleted file mode 100644 index e5a4575f15..0000000000 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionMatcher.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.config; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities; - -public final class MqttConditionMatcher -{ - private final Matcher topicMatch; - private final MqttCapabilities capabilitiesMatch; - - public MqttConditionMatcher( - MqttConditionConfig condition) - { - this.topicMatch = condition.topic != null ? asMatcher(condition.topic) : null; - this.capabilitiesMatch = condition.capabilities; - } - - public boolean matches( - MqttCapabilities capabilities) - { - return matchesCapabilities(capabilities); - } - - public boolean matches( - String topic, - MqttCapabilities capabilities) - { - return matchesTopic(topic) && - matchesCapabilities(capabilities); - } - - private boolean matchesTopic( - String topic) - { - return this.topicMatch == null || this.topicMatch.reset(topic).matches(); - } - - private boolean matchesCapabilities( - MqttCapabilities capabilities) - { - return this.capabilitiesMatch == null || (this.capabilitiesMatch.value() & capabilities.value()) != 0; - } - - private static Matcher asMatcher( - String wildcard) - { - return Pattern.compile(wildcard - .replace(".", "\\.") - .replace("$", "\\$") - .replace("+", "[^/]*") - .replace("#", ".*")).matcher(""); - } -} diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java b/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java deleted file mode 100644 index a307aaab82..0000000000 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; - -public class MqttClientFactory -{ -} diff --git a/incubator/binding-mqtt/src/main/moditect/module-info.java b/incubator/binding-mqtt/src/main/moditect/module-info.java deleted file mode 100644 index 2a88753954..0000000000 --- a/incubator/binding-mqtt/src/main/moditect/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -module io.aklivity.zilla.runtime.binding.mqtt -{ - requires io.aklivity.zilla.runtime.engine; - - provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi - with io.aklivity.zilla.runtime.binding.mqtt.internal.MqttBindingFactorySpi; - - provides io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi - with io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttConditionConfigAdapter; -} diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapterTest.java b/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapterTest.java deleted file mode 100644 index ac0a56e001..0000000000 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapterTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.config; - -import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities.PUBLISH_ONLY; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities.SUBSCRIBE_ONLY; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; - -import jakarta.json.bind.Jsonb; -import jakarta.json.bind.JsonbBuilder; -import jakarta.json.bind.JsonbConfig; - -import org.junit.Before; -import org.junit.Test; - -public class MqttConditionConfigAdapterTest -{ - private Jsonb jsonb; - - @Before - public void initJson() - { - JsonbConfig config = new JsonbConfig() - .withAdapters(new MqttConditionConfigAdapter()); - jsonb = JsonbBuilder.create(config); - } - - @Test - public void shouldReadCondition() - { - String text = - "{" + - "\"topic\": \"test\"," + - "\"capabilities\": \"publish_only\"" + - "}"; - - MqttConditionConfig condition = jsonb.fromJson(text, MqttConditionConfig.class); - - assertThat(condition, not(nullValue())); - assertThat(condition.topic, equalTo("test")); - assertThat(condition.capabilities, equalTo(PUBLISH_ONLY)); - } - - @Test - public void shouldWriteCondition() - { - MqttConditionConfig condition = new MqttConditionConfig("test", SUBSCRIBE_ONLY); - - String text = jsonb.toJson(condition); - - assertThat(text, not(nullValue())); - assertThat(text, equalTo("{\"topic\":\"test\",\"capabilities\":\"subscribe_only\"}")); - } -} diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/ConnectionIT.java b/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/ConnectionIT.java deleted file mode 100644 index 1abac32291..0000000000 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/ConnectionIT.java +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; - -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.CONNECT_TIMEOUT_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.KEEP_ALIVE_MINIMUM_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.MAXIMUM_QOS_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.RETAIN_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_EXPIRY_INTERVAL_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SHARED_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.WILDCARD_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; -import io.aklivity.zilla.runtime.engine.test.annotation.Configure; - -public class ConnectionIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(PUBLISH_TIMEOUT, 1L) - .configure(ENGINE_DRAIN_ON_CLOSE, false) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") - .external("app0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.successful/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldConnect() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.server.assigned.client.id/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldConnectWithServerAssignedClientId() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.missing.client.id/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectMissingClientId() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/disconnect/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldConnectThenDisconnect() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.invalid.protocol.version/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectInvalidProtocolVersion() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.invalid.flags/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectMalformedConnectPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.invalid.authentication.method/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectBadAuthenticationMethod() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/disconnect.reject.invalid.fixed.header.flags/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectMalformedDisconnectPacket() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.0-2] - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.second.connect/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectSecondConnectPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.successful.fragmented/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldConnectFragmented() throws Exception - { - k3po.finish(); - } - - // [MQTT-3.1.0-1] - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.other.packet.before.connect/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectOtherPacketBeforeConnect() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.topic.alias.maximum.repeated/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWhenTopicAliasMaximumRepeated() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/client.sent.close/client", - "${app}/client.sent.abort/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveClientSentClose() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/client.sent.abort/client", - "${app}/client.sent.abort/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveClientSentAbort() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/client.sent.reset/client", - "${app}/client.sent.abort/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveClientSentReset() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/disconnect.after.keep.alive.timeout/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "1") - public void shouldDisconnectClientAfterKeepAliveTimeout() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.timeout.before.connect/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - @Configure(name = CONNECT_TIMEOUT_NAME, value = "1") - public void shouldTimeoutBeforeConnect() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.maximum.qos.0/client"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldConnectWithMaximumQos0() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.retain.not.supported/client"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = RETAIN_AVAILABLE_NAME, value = "false") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldConnectWithRetainNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.will.retain.not.supported/client"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = RETAIN_AVAILABLE_NAME, value = "false") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWillRetainNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.password.flag.no.password/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWithPasswordFlagSetNoPassword() throws Exception - { - k3po.finish(); - } - - @Ignore - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.password.no.password.flag/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWithPasswordNoPasswordFlag() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.username.flag.only/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWithUsernameFlagNoUsername() throws Exception - { - k3po.finish(); - } - - @Ignore - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.username.flag.missing/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWithUsernameNoUsernameFlag() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.will.payload.missing/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWillPayloadMissing() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.will.properties.missing/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWillPropertiesMissing() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.reject.will.topic.missing/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectConnectWillTopicMissing() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.will.invalid.will.qos/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectInvalidWillQos() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.will.reject.will.qos.1.without.will.flag/client"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectWillQos1WithoutWillFlag() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.will.reject.will.qos.2.without.will.flag/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectWillQos2WithoutWillFlag() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.will.reject.will.retain.without.will.flag/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectWillRetainWithoutWillFlag() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.max.packet.size.exceeded/client", - "${app}/connect.max.packet.size.exceeded/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldIgnorePublishPacketBiggerThanMaxPacketSize() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.server.defined.keep.alive/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "10") - public void shouldConnectWithServerDefinedKeepAlive() throws Exception - { - k3po.start(); - Thread.sleep(2000); - k3po.notifyBarrier("WAIT_2_SECONDS"); - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/connect.subscribe.unfragmented/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "10") - public void shouldConnectAndSubscribeUnfragmented() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/PingIT.java b/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/PingIT.java deleted file mode 100644 index bb76bea42c..0000000000 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/PingIT.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; - -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.KEEP_ALIVE_MINIMUM_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.MAXIMUM_QOS_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_EXPIRY_INTERVAL_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SHARED_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.WILDCARD_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; -import io.aklivity.zilla.runtime.engine.test.annotation.Configure; - -public class PingIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(PUBLISH_TIMEOUT, 1L) - .configure(ENGINE_DRAIN_ON_CLOSE, false) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") - .external("app0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/ping/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldConnectThenPingRequestResponse() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/ping.keep.alive/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "1") - public void shouldPingAtKeepAliveInterval() throws Exception - { - k3po.start(); - Thread.sleep(1000); - k3po.notifyBarrier("WAIT_1_SECOND"); - Thread.sleep(1000); - k3po.notifyBarrier("WAIT_1_SECOND2"); - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/PublishIT.java b/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/PublishIT.java deleted file mode 100644 index 389414a5eb..0000000000 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/PublishIT.java +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; - -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.MAXIMUM_QOS_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.PUBLISH_TIMEOUT_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.RETAIN_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_EXPIRY_INTERVAL_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SHARED_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.TOPIC_ALIAS_MAXIMUM_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.WILDCARD_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; -import io.aklivity.zilla.runtime.engine.test.annotation.Configure; - -public class PublishIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(PUBLISH_TIMEOUT, 1L) - .configure(ENGINE_DRAIN_ON_CLOSE, false) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") - .external("app0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.one.message/client", - "${app}/publish.one.message/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.retained/client", - "${app}/publish.retained/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishRetainedMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.message.with.topic.alias/client", - "${app}/publish.message.with.topic.alias/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishMessageWithTopicAlias() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.multiple.messages/client", - "${app}/publish.multiple.messages/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishMultipleMessages() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.multiple.messages.unfragmented/client", - "${app}/publish.multiple.messages/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishMultipleMessagesUnfragmented() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.one.message.subscribe.unfragmented/client", - "${app}/publish.one.message.subscribe.unfragmented/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishOneMessageSubscribeUnfragmented() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.multiple.messages.with.delay/client", - "${app}/publish.multiple.messages/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - @Configure(name = PUBLISH_TIMEOUT_NAME, value = "5") - public void shouldPublishMultipleMessagesWithDelay() throws Exception - { - k3po.start(); - k3po.awaitBarrier("PUBLISHED_MESSAGE_TWO"); - Thread.sleep(500); - k3po.notifyBarrier("PUBLISH_MESSAGE_THREE"); - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.messages.with.topic.alias.distinct/client", - "${app}/publish.messages.with.topic.alias.distinct/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishMessagesWithTopicAliasDistinct() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.messages.with.topic.alias.repeated/client", - "${app}/publish.messages.with.topic.alias.repeated/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishMessagesWithTopicAliasRepeated() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.messages.with.topic.alias.replaced/client", - "${app}/publish.messages.with.topic.alias.replaced/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "1") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishMessagesWithTopicAliasReplaced() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.messages.with.topic.alias.invalid.scope/client", - "${app}/publish.messages.with.topic.alias.invalid.scope/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "1") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldSendMessagesWithTopicAliasInvalidScope() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.topic.not.routed/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectTopicNotRouted() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.topic.alias.exceeds.maximum/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishWhenTopicAliasExceedsMaximum() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.topic.alias.repeated/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishWithMultipleTopicAliases() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.client.sent.subscription.id/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishClientSentSubscriptionId() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.invalid.payload.format/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishInvalidPayloadFormat() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.qos1.not.supported/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "0") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublisQos1NotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.qos2.not.supported/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "0") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublisQos2NotSupported() throws Exception - { - k3po.finish(); - } - - @Ignore - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.qos0.with.packet.id/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishQos0WithPacketId() throws Exception - { - k3po.finish(); - } - - @Ignore - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.qos1.without.packet.id/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishQos1WithoutPacketId() throws Exception - { - k3po.finish(); - } - - @Ignore - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.qos2.without.packet.id/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishQos2WithoutPacketId() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.reject.retain.not.supported/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = RETAIN_AVAILABLE_NAME, value = "false") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectPublishRetainNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.with.user.property/client", - "${app}/publish.with.user.property/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishWithUserProperty() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.with.user.properties.distinct/client", - "${app}/publish.with.user.properties.distinct/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishWithDistinctUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.with.user.properties.repeated/client", - "${app}/publish.with.user.properties.repeated/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishWithRepeatedUserProperties() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.empty.retained.message/client", - "${app}/publish.empty.retained.message/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishEmptyRetainedMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/publish.empty.message/client", - "${app}/publish.empty.message/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldPublishEmptyMessage() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/SessionIT.java b/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/SessionIT.java deleted file mode 100644 index 4419c5cbac..0000000000 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/SessionIT.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; - -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.KEEP_ALIVE_MINIMUM_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.MAXIMUM_QOS_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_EXPIRY_INTERVAL_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SHARED_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.WILDCARD_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; -import io.aklivity.zilla.runtime.engine.test.annotation.Configure; - -public class SessionIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(PUBLISH_TIMEOUT, 1L) - .configure(ENGINE_DRAIN_ON_CLOSE, false) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") - .external("app0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.connect.with.session.expiry/client", - "${app}/session.connect.with.session.expiry/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldConnectWithSessionExpiry() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.subscribe/client", - "${app}/session.subscribe/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldSubscribeSaveSubscriptionsInSession() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.subscribe.via.session.state/client", - "${app}/session.subscribe.via.session.state/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldSubscribeViaSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.unsubscribe.after.subscribe/client", - "${app}/session.unsubscribe.after.subscribe/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldUnsubscribeSaveNewSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.unsubscribe.after.subscribe.deferred/client", - "${app}/session.unsubscribe.after.subscribe.deferred/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldUnsubscribeAfterSubscribeDeferred() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.subscribe/client", - "${app}/session.unsubscribe.via.session.state/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldUnsubscribeViaSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.will.message.retain/client", - "${app}/session.will.message.retain/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldStoreWillMessageInSessionState() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.will.message.normal.disconnect/client", - "${app}/session.will.message.normal.disconnect/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldCloseSessionNormalDisconnect() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.will.message.disconnect.with.will.message/client", - "${app}/session.will.message.disconnect.with.will.message/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldCloseSessionDisconnectWithWill() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.will.message.no.ping.within.keep.alive/client", - "${app}/session.will.message.no.ping.within.keep.alive/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "1") - public void shouldCloseSessionWithKeepAliveExpired() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.exists.clean.start/client", - "${app}/session.exists.clean.start/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldCloseExistingConnectionCleanStart() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.abort.reconnect.non.clean.start/client", - "${app}/session.abort.reconnect.non.clean.start/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldClientAbortAndReconnectWithNonCleanStart() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/session.client.takeover/client", - "${app}/session.client.takeover/server"}) - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "10") - public void shouldClientTakeOverSession() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/SubscribeIT.java b/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/SubscribeIT.java deleted file mode 100644 index ecd016e1ed..0000000000 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/SubscribeIT.java +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; - -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.MAXIMUM_QOS_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.NO_LOCAL_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_EXPIRY_INTERVAL_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SHARED_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SUBSCRIPTION_IDENTIFIERS_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.WILDCARD_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; -import io.aklivity.zilla.runtime.engine.test.annotation.Configure; - -public class SubscribeIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(PUBLISH_TIMEOUT, 1L) - .configure(ENGINE_DRAIN_ON_CLOSE, false) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") - .external("app0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.one.message/client", - "${app}/subscribe.one.message/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveOneMessage() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.one.message.receive.response.topic.and.correlation.data/client", - "${app}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveCorrelationData() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.one.message.user.properties.unaltered/client", - "${app}/subscribe.one.message.user.properties.unaltered/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.one.message.with.invalid.subscription.id/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveOneMessageWithInvalidSubscriptionId() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filter.single.exact/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterExact() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filter.multi.level.wildcard/client", - "${app}/subscribe.topic.filter.multi.level.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filter.single.and.multi.level.wildcard/client", - "${app}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterSingleAndMultiLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filter.single.level.wildcard/client", - "${app}/subscribe.topic.filter.single.level.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filter.two.single.level.wildcard/client", - "${app}/subscribe.topic.filter.two.single.level.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterTwoSingleLevelWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filters.aggregated.both.exact/client", - "${app}/subscribe.topic.filters.aggregated.both.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterAggregatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filters.isolated.both.exact/client", - "${app}/subscribe.topic.filters.isolated.both.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterIsolatedBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filters.isolated.both.wildcard/client", - "${app}/subscribe.topic.filters.isolated.both.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterIsolatedBothWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", - "${app}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterAggregatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filters.disjoint.wildcards/client", - "${app}/subscribe.topic.filters.disjoint.wildcards/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterDisjointWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filters.isolated.exact.and.wildcard/client", - "${app}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterIsolatedExactAndWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.topic.filters.overlapping.wildcards/client", - "${app}/subscribe.topic.filters.overlapping.wildcards/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldFilterOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.get.retained.as.published/client", - "${app}/subscribe.get.retained.as.published/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveRetainedAsPublished() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.qos0.publish.retained.no.replay/client", - "${app}/subscribe.qos0.publish.retained.no.replay/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldNotReplayRetained() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.qos0.replay.retained.no.packet.id/client", - "${app}/subscribe.qos0.replay.retained.no.packet.id/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveAndReplayRetainedQos0() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.reject.no.local/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - @Configure(name = NO_LOCAL_NAME, value = "false") - public void shouldRejectNoLocal() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.receive.message/client", - "${app}/subscribe.receive.message/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveOneMessageAfterPublish() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.receive.message.overlapping.wildcard/client", - "${app}/subscribe.receive.message.overlapping.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveMessageOverlappingWildcard() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.receive.message.wildcard/client", - "${app}/subscribe.receive.message.wildcard/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveOneMessageWithPatternTopic() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.retain.as.published/client", - "${app}/subscribe.retain.as.published/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldReceiveRetainAsPublished() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.publish.no.local/client", - "${app}/subscribe.publish.no.local/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldNotReceivePublishLocal() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.invalid.fixed.header.flags/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectMalformedPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.invalid.topic.filter/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectInvalidTopicFilter() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.reject.wildcard.subscriptions.not.supported/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "false") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectWildcardSubscriptionsNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.reject.subscription.ids.not.supported/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SUBSCRIPTION_IDENTIFIERS_AVAILABLE_NAME, value = "false") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectSubscriptionIdentifiersNotSupported() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/subscribe.reject.shared.subscriptions.not.supported/client"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "false") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectSharedSubscriptionsNotSupported() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/UnsubscribeIT.java b/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/UnsubscribeIT.java deleted file mode 100644 index 12830e9772..0000000000 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/UnsubscribeIT.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; - -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.MAXIMUM_QOS_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SESSION_EXPIRY_INTERVAL_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SHARED_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.WILDCARD_SUBSCRIPTION_AVAILABLE_NAME; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.rules.RuleChain.outerRule; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.kaazing.k3po.junit.annotation.Specification; -import org.kaazing.k3po.junit.rules.K3poRule; - -import io.aklivity.zilla.runtime.engine.test.EngineRule; -import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; -import io.aklivity.zilla.runtime.engine.test.annotation.Configure; - -public class UnsubscribeIT -{ - private final K3poRule k3po = new K3poRule() - .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") - .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); - - private final TestRule timeout = new DisableOnDebug(new Timeout(20, SECONDS)); - - private final EngineRule engine = new EngineRule() - .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - .configure(PUBLISH_TIMEOUT, 1L) - .configure(ENGINE_DRAIN_ON_CLOSE, false) - .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") - .external("app0") - .clean(); - - @Rule - public final TestRule chain = outerRule(engine).around(k3po).around(timeout); - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.after.subscribe/client", - "${app}/unsubscribe.after.subscribe/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldAcknowledge() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.topic.filter.single/client", - "${app}/unsubscribe.topic.filter.single/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldAcknowledgeSingleTopicFilters() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.publish.unfragmented/client", - "${app}/unsubscribe.publish.unfragmented/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldAcknowledgeAndPublishUnfragmented() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.aggregated.topic.filters.both.exact/client", - "${app}/unsubscribe.aggregated.topic.filters.both.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldAcknowledgeAggregatedTopicFiltersBothExact() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.no.matching.subscription/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldAcknowledgeNoMatchingSubscription() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.reject.invalid.fixed.header.flags/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectMalformedPacket() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.reject.missing.packet.id/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectWithoutPacketId() throws Exception - { - k3po.finish(); - } - - @Test - @Configuration("server.yaml") - @Specification({ - "${net}/unsubscribe.reject.no.topic.filter/client", - "${app}/subscribe.topic.filter.single.exact/server"}) - @Configure(name = SESSION_AVAILABLE_NAME, value = "false") - @Configure(name = WILDCARD_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = SHARED_SUBSCRIPTION_AVAILABLE_NAME, value = "true") - @Configure(name = MAXIMUM_QOS_NAME, value = "2") - @Configure(name = SESSION_EXPIRY_INTERVAL_NAME, value = "0") - public void shouldRejectNoTopicFilter() throws Exception - { - k3po.finish(); - } -} diff --git a/incubator/binding-mqtt-kafka.spec/COPYRIGHT b/incubator/command-config/COPYRIGHT similarity index 100% rename from incubator/binding-mqtt-kafka.spec/COPYRIGHT rename to incubator/command-config/COPYRIGHT diff --git a/incubator/binding-mqtt-kafka.spec/LICENSE b/incubator/command-config/LICENSE similarity index 100% rename from incubator/binding-mqtt-kafka.spec/LICENSE rename to incubator/command-config/LICENSE diff --git a/incubator/binding-mqtt-kafka/NOTICE b/incubator/command-config/NOTICE similarity index 100% rename from incubator/binding-mqtt-kafka/NOTICE rename to incubator/command-config/NOTICE diff --git a/incubator/binding-mqtt-kafka.spec/NOTICE.template b/incubator/command-config/NOTICE.template similarity index 100% rename from incubator/binding-mqtt-kafka.spec/NOTICE.template rename to incubator/command-config/NOTICE.template diff --git a/incubator/binding-mqtt-kafka.spec/mvnw b/incubator/command-config/mvnw similarity index 100% rename from incubator/binding-mqtt-kafka.spec/mvnw rename to incubator/command-config/mvnw diff --git a/incubator/binding-mqtt-kafka.spec/mvnw.cmd b/incubator/command-config/mvnw.cmd similarity index 100% rename from incubator/binding-mqtt-kafka.spec/mvnw.cmd rename to incubator/command-config/mvnw.cmd diff --git a/incubator/command-config/pom.xml b/incubator/command-config/pom.xml new file mode 100644 index 0000000000..cc6f121890 --- /dev/null +++ b/incubator/command-config/pom.xml @@ -0,0 +1,178 @@ + + + + 4.0.0 + + io.aklivity.zilla + incubator + 0.9.52 + ../pom.xml + + + command-config + zilla::incubator::command-config + + + + Aklivity Community License Agreement + https://www.aklivity.io/aklivity-community-license/ + repo + + + + + 11 + 11 + 0.60 + 4 + + + + + ${project.groupId} + engine.spec + ${project.version} + provided + + + ${project.groupId} + engine + ${project.version} + provided + + + ${project.groupId} + command + ${project.version} + provided + + + io.aklivity.zilla + binding-http + ${project.version} + provided + + + io.aklivity.zilla + binding-mqtt + ${project.version} + provided + + + io.aklivity.zilla + binding-tcp + ${project.version} + provided + + + io.aklivity.zilla + binding-tls + ${project.version} + provided + + + io.aklivity.zilla + guard-jwt + ${project.version} + provided + + + io.aklivity.zilla + vault-filesystem + ${project.version} + provided + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + org.jasig.maven + maven-notice-plugin + + + com.mycila + license-maven-plugin + + + src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/**/* + src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/**/* + + + + + maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.moditect + moditect-maven-plugin + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.jacoco + jacoco-maven-plugin + + + io/aklivity/zilla/runtime/command/config/internal/types/**/*.class + io/aklivity/zilla/runtime/command/config/internal/openapi/model/*.class + io/aklivity/zilla/runtime/command/config/internal/openapi/model2/*.class + io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/*.class + io/aklivity/zilla/runtime/command/config/internal/asyncapi/model2/*.class + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + ${jacoco.coverage.ratio} + + + CLASS + MISSEDCOUNT + ${jacoco.missed.count} + + + + + + + + ${project.groupId} + flyweight-maven-plugin + ${project.version} + + core + io.aklivity.zilla.runtime.command.config.internal.types + + + + + generate + + + + + + + diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/ZillaConfigCommandSpi.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/ZillaConfigCommandSpi.java new file mode 100644 index 0000000000..6a526cf02b --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/ZillaConfigCommandSpi.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal; + +import com.github.rvesse.airline.builder.CliBuilder; + +import io.aklivity.zilla.runtime.command.ZillaCommandSpi; +import io.aklivity.zilla.runtime.command.config.internal.airline.ZillaConfigCommand; + +public class ZillaConfigCommandSpi implements ZillaCommandSpi +{ + @Override + public void mixin( + CliBuilder builder) + { + builder.withCommand(ZillaConfigCommand.class); + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ConfigGenerator.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ConfigGenerator.java new file mode 100644 index 0000000000..aa2f1ddc19 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ConfigGenerator.java @@ -0,0 +1,37 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.airline; + +import java.util.List; +import java.util.regex.Pattern; + +public abstract class ConfigGenerator +{ + public abstract String generate(); + + protected final String unquoteEnvVars( + String yaml, + List unquotedEnvVars) + { + for (String envVar : unquotedEnvVars) + { + yaml = yaml.replaceAll( + Pattern.quote(String.format("\"${{env.%s}}\"", envVar)), + String.format("\\${{env.%s}}", envVar) + ); + } + return yaml; + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ZillaConfigCommand.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ZillaConfigCommand.java new file mode 100644 index 0000000000..838c8d5ad9 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ZillaConfigCommand.java @@ -0,0 +1,80 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.airline; + +import static org.agrona.LangUtil.rethrowUnchecked; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; +import java.util.function.Function; + +import com.github.rvesse.airline.annotations.Command; +import com.github.rvesse.airline.annotations.Option; +import com.github.rvesse.airline.annotations.restrictions.AllowedValues; +import com.github.rvesse.airline.annotations.restrictions.Required; + +import io.aklivity.zilla.runtime.command.ZillaCommand; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.http.proxy.AsyncApiHttpProxyConfigGenerator; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.mqtt.proxy.AsyncApiMqttProxyConfigGenerator; +import io.aklivity.zilla.runtime.command.config.internal.openapi.http.proxy.OpenApiHttpProxyConfigGenerator; + +@Command(name = "generate", description = "Generate configuration file") +public final class ZillaConfigCommand extends ZillaCommand +{ + private static final Map> GENERATORS = Map.of( + "openapi.http.proxy", OpenApiHttpProxyConfigGenerator::new, + "asyncapi.http.proxy", AsyncApiHttpProxyConfigGenerator::new, + "asyncapi.mqtt.proxy", AsyncApiMqttProxyConfigGenerator::new + ); + + @Option(name = {"-t", "--template"}, + description = "Template name") + @Required + @AllowedValues(allowedValues = { + "openapi.http.proxy", + "asyncapi.http.proxy", + "asyncapi.mqtt.proxy" + }) + public String template; + + @Option(name = {"-i", "--input"}, + description = "Input filename", + typeConverterProvider = ZillaConfigCommandPathConverterProvider.class) + public Path input; + + @Option(name = {"-o", "--output"}, + description = "Output filename", + typeConverterProvider = ZillaConfigCommandPathConverterProvider.class) + public Path output = Paths.get("zilla.yaml"); + + @Override + public void run() + { + try (InputStream inputStream = new FileInputStream(input.toFile())) + { + ConfigGenerator generator = GENERATORS.get(template).apply(inputStream); + Files.writeString(output, generator.generate()); + } + catch (Exception ex) + { + ex.printStackTrace(); + rethrowUnchecked(ex); + } + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ZillaConfigCommandPathConverterProvider.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ZillaConfigCommandPathConverterProvider.java new file mode 100644 index 0000000000..6160cc405d --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/airline/ZillaConfigCommandPathConverterProvider.java @@ -0,0 +1,63 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.airline; + +import java.nio.file.Paths; + +import com.github.rvesse.airline.model.ArgumentsMetadata; +import com.github.rvesse.airline.model.OptionMetadata; +import com.github.rvesse.airline.parser.ParseState; +import com.github.rvesse.airline.types.TypeConverter; +import com.github.rvesse.airline.types.TypeConverterProvider; +import com.github.rvesse.airline.types.numerics.NumericTypeConverter; + +public final class ZillaConfigCommandPathConverterProvider implements TypeConverterProvider +{ + private final ZillaDumpCommandPathConverter converter = new ZillaDumpCommandPathConverter(); + + private final class ZillaDumpCommandPathConverter implements TypeConverter + { + @Override + public void setNumericConverter( + NumericTypeConverter converter) + { + } + + @Override + public Object convert( + String name, + Class type, + String value) + { + return Paths.get(value); + } + } + + @Override + public TypeConverter getTypeConverter( + OptionMetadata option, + ParseState state) + { + return converter; + } + + @Override + public TypeConverter getTypeConverter( + ArgumentsMetadata arguments, + ParseState state) + { + return converter; + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/AsyncApiHttpProxyConfigGenerator.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/AsyncApiHttpProxyConfigGenerator.java new file mode 100644 index 0000000000..0d0276ec12 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/AsyncApiHttpProxyConfigGenerator.java @@ -0,0 +1,504 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.http.proxy; + +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.CROSS_ORIGIN; +import static io.aklivity.zilla.runtime.engine.config.KindConfig.CLIENT; +import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; +import static java.util.Objects.requireNonNull; +import static org.agrona.LangUtil.rethrowUnchecked; + +import java.io.InputStream; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.json.Json; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; + +import io.aklivity.zilla.runtime.binding.http.config.HttpConditionConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfigBuilder; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfig; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfig; +import io.aklivity.zilla.runtime.command.config.internal.airline.ConfigGenerator; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.AsyncApi; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.Item; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.Message; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.Operation; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.Server; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.view.ChannelView; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.view.ServerView; +import io.aklivity.zilla.runtime.engine.config.BindingConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.ConfigWriter; +import io.aklivity.zilla.runtime.engine.config.GuardedConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.NamespaceConfig; +import io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.RouteConfigBuilder; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; + +public class AsyncApiHttpProxyConfigGenerator extends ConfigGenerator +{ + private final InputStream input; + + private AsyncApi asyncApi; + private int[] allPorts; + private int[] httpPorts; + private int[] httpsPorts; + private boolean isPlainEnabled; + private boolean isTlsEnabled; + private Map securitySchemes; + private String authorizationHeader; + private boolean isJwtEnabled; + + public AsyncApiHttpProxyConfigGenerator( + InputStream input) + { + this.input = input; + } + + @Override + public String generate() + { + this.asyncApi = parseAsyncApi(input); + this.allPorts = resolveAllPorts(); + this.httpPorts = resolvePortsForScheme("http"); + this.httpsPorts = resolvePortsForScheme("https"); + this.isPlainEnabled = httpPorts != null; + this.isTlsEnabled = httpsPorts != null; + this.securitySchemes = resolveSecuritySchemes(); + this.authorizationHeader = resolveAuthorizationHeader(); + this.isJwtEnabled = !securitySchemes.isEmpty(); + ConfigWriter configWriter = new ConfigWriter(null); + String yaml = configWriter.write(createNamespace(), createEnvVarsPatch()); + return unquoteEnvVars(yaml, unquotedEnvVars()); + } + + private AsyncApi parseAsyncApi( + InputStream inputStream) + { + AsyncApi asyncApi = null; + try (Jsonb jsonb = JsonbBuilder.create()) + { + asyncApi = jsonb.fromJson(inputStream, AsyncApi.class); + } + catch (Exception ex) + { + rethrowUnchecked(ex); + } + return asyncApi; + } + + private int[] resolveAllPorts() + { + int[] ports = new int[asyncApi.servers.size()]; + String[] keys = asyncApi.servers.keySet().toArray(String[]::new); + for (int i = 0; i < asyncApi.servers.size(); i++) + { + ServerView server = ServerView.of(asyncApi.servers.get(keys[i])); + URI url = server.url(); + ports[i] = url.getPort(); + } + return ports; + } + + private int[] resolvePortsForScheme( + String scheme) + { + requireNonNull(scheme); + int[] ports = null; + URI url = findFirstServerUrlWithScheme(scheme); + if (url != null) + { + ports = new int[] {url.getPort()}; + } + return ports; + } + + private URI findFirstServerUrlWithScheme( + String scheme) + { + requireNonNull(scheme); + URI result = null; + for (String key : asyncApi.servers.keySet()) + { + ServerView server = ServerView.of(asyncApi.servers.get(key)); + if (scheme.equals(server.url().getScheme())) + { + result = server.url(); + break; + } + } + return result; + } + + private Map resolveSecuritySchemes() + { + requireNonNull(asyncApi); + Map result = new HashMap<>(); + if (asyncApi.components != null && asyncApi.components.securitySchemes != null) + { + for (String securitySchemeName : asyncApi.components.securitySchemes.keySet()) + { + String guardType = asyncApi.components.securitySchemes.get(securitySchemeName).bearerFormat; + if ("jwt".equals(guardType)) + { + result.put(securitySchemeName, guardType); + } + } + } + return result; + } + + private String resolveAuthorizationHeader() + { + requireNonNull(asyncApi); + requireNonNull(asyncApi.components); + requireNonNull(asyncApi.components.messages); + String result = null; + for (Map.Entry entry: asyncApi.components.messages.entrySet()) + { + Message message = entry.getValue(); + if (message.headers != null && message.headers.properties != null) + { + Item authorization = message.headers.properties.get("authorization"); + if (authorization != null) + { + result = authorization.description; + break; + } + } + } + return result; + } + + private NamespaceConfig createNamespace() + { + return NamespaceConfig.builder() + .name("example") + .binding() + .name("tcp_server0") + .type("tcp") + .kind(SERVER) + .options(TcpOptionsConfig::builder) + .host("0.0.0.0") + .ports(allPorts) + .build() + .inject(this::injectPlainTcpRoute) + .inject(this::injectTlsTcpRoute) + .build() + .inject(this::injectTlsServer) + .binding() + .name("http_server0") + .type("http") + .kind(SERVER) + .options(HttpOptionsConfig::builder) + .access() + .policy(CROSS_ORIGIN) + .build() + .inject(this::injectHttpServerOptions) + .build() + .inject(this::injectHttpServerRoutes) + .build() + .binding() + .name("http_client0") + .type("http") + .kind(CLIENT) + .exit(isTlsEnabled ? "tls_client0" : "tcp_client0") + .build() + .inject(this::injectTlsClient) + .binding() + .name("tcp_client0") + .type("tcp") + .kind(CLIENT) + .options(TcpOptionsConfig::builder) + .host("") // env + .ports(new int[]{0}) // env + .build() + .build() + .inject(this::injectGuard) + .inject(this::injectVaults) + .build(); + } + + private BindingConfigBuilder> injectPlainTcpRoute( + BindingConfigBuilder> binding) + { + if (isPlainEnabled) + { + binding + .route() + .when(TcpConditionConfig::builder) + .ports(httpPorts) + .build() + .exit("http_server0") + .build(); + } + return binding; + } + + private BindingConfigBuilder> injectTlsTcpRoute( + BindingConfigBuilder> binding) + { + if (isTlsEnabled) + { + binding + .route() + .when(TcpConditionConfig::builder) + .ports(httpsPorts) + .build() + .exit("tls_server0") + .build(); + } + return binding; + } + + private NamespaceConfigBuilder injectTlsServer( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .binding() + .name("tls_server0") + .type("tls") + .kind(SERVER) + .options(TlsOptionsConfig::builder) + .keys(List.of("")) // env + .sni(List.of("")) // env + .alpn(List.of("")) // env + .build() + .vault("server") + .exit("http_server0") + .build(); + } + return namespace; + } + + private HttpOptionsConfigBuilder>> injectHttpServerOptions( + HttpOptionsConfigBuilder>> options) + { + if (isJwtEnabled) + { + options + .authorization() + .name("jwt0") + .credentials() + .header() + .name("authorization") + .pattern(authorizationHeader) + .build() + .build() + .build(); + } + return options; + } + + private BindingConfigBuilder> injectHttpServerRoutes( + BindingConfigBuilder> binding) + { + for (Map.Entry entry : asyncApi.servers.entrySet()) + { + ServerView server = ServerView.of(entry.getValue()); + for (String name : asyncApi.operations.keySet()) + { + Operation operation = asyncApi.operations.get(name); + ChannelView channel = ChannelView.of(asyncApi.channels, operation.channel); + String path = channel.address().replaceAll("\\{[^}]+\\}", "*"); + String method = operation.bindings.get("http").method; + binding + .route() + .exit("http_client0") + .when(HttpConditionConfig::builder) + .header(":scheme", server.scheme()) + .header(":authority", server.authority()) + .header(":path", path) + .header(":method", method) + .build() + .inject(route -> injectHttpServerRouteGuarded(route, server)) + .build(); + } + } + return binding; + } + + private RouteConfigBuilder injectHttpServerRouteGuarded( + RouteConfigBuilder route, + ServerView server) + { + if (server.security() != null) + { + for (Map> securityItem : server.security()) + { + for (String securityItemLabel : securityItem.keySet()) + { + if (isJwtEnabled && "jwt".equals(securitySchemes.get(securityItemLabel))) + { + route + .guarded() + .name("jwt0") + .inject(guarded -> injectGuardedRoles(guarded, securityItem.get(securityItemLabel))) + .build(); + break; + } + } + } + } + return route; + } + + private GuardedConfigBuilder injectGuardedRoles( + GuardedConfigBuilder guarded, + List roles) + { + for (String role : roles) + { + guarded.role(role); + } + return guarded; + } + + private NamespaceConfigBuilder injectTlsClient( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .binding() + .name("tls_client0") + .type("tls") + .kind(CLIENT) + .options(TlsOptionsConfig::builder) + .trust(List.of("")) // env + .sni(List.of("")) // env + .alpn(List.of("")) // env + .trustcacerts(true) + .build() + .vault("client") + .exit("tcp_client0") + .build(); + } + return namespace; + } + + private NamespaceConfigBuilder injectGuard( + NamespaceConfigBuilder namespace) + { + if (isJwtEnabled) + { + namespace + .guard() + .name("jwt0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .issuer("") // env + .audience("") // env + .key() + .alg("").kty("").kid("").use("").n("").e("").crv("").x("").y("") // env + .build() + .build() + .build(); + } + return namespace; + } + + private NamespaceConfigBuilder injectVaults( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .vault() + .name("client") + .type("filesystem") + .options(FileSystemOptionsConfig::builder) + .trust() + .store("") // env + .type("") // env + .password("") // env + .build() + .build() + .build() + .vault() + .name("server") + .type("filesystem") + .options(FileSystemOptionsConfig::builder) + .keys() + .store("") // env + .type("") // env + .password("") //env + .build() + .build() + .build(); + } + return namespace; + } + + private JsonPatch createEnvVarsPatch() + { + JsonPatchBuilder patch = Json.createPatchBuilder(); + patch.replace("/bindings/tcp_client0/options/host", "${{env.TCP_CLIENT_HOST}}"); + patch.replace("/bindings/tcp_client0/options/port", "${{env.TCP_CLIENT_PORT}}"); + + if (isJwtEnabled) + { + // jwt0 guard + patch.replace("/guards/jwt0/options/issuer", "${{env.JWT_ISSUER}}"); + patch.replace("/guards/jwt0/options/audience", "${{env.JWT_AUDIENCE}}"); + patch.replace("/guards/jwt0/options/keys/0/alg", "${{env.JWT_ALG}}"); + patch.replace("/guards/jwt0/options/keys/0/kty", "${{env.JWT_KTY}}"); + patch.replace("/guards/jwt0/options/keys/0/kid", "${{env.JWT_KID}}"); + patch.replace("/guards/jwt0/options/keys/0/use", "${{env.JWT_USE}}"); + patch.replace("/guards/jwt0/options/keys/0/n", "${{env.JWT_N}}"); + patch.replace("/guards/jwt0/options/keys/0/e", "${{env.JWT_E}}"); + patch.replace("/guards/jwt0/options/keys/0/crv", "${{env.JWT_CRV}}"); + patch.replace("/guards/jwt0/options/keys/0/x", "${{env.JWT_X}}"); + patch.replace("/guards/jwt0/options/keys/0/y", "${{env.JWT_Y}}"); + } + + if (isTlsEnabled) + { + // tls_server0 binding + patch.replace("/bindings/tls_server0/options/keys/0", "${{env.TLS_SERVER_KEY}}"); + patch.replace("/bindings/tls_server0/options/sni/0", "${{env.TLS_SERVER_SNI}}"); + patch.replace("/bindings/tls_server0/options/alpn/0", "${{env.TLS_SERVER_ALPN}}"); + // tls_client0 binding + patch.replace("/bindings/tls_client0/options/trust/0", "${{env.TLS_CLIENT_TRUST}}"); + patch.replace("/bindings/tls_client0/options/sni/0", "${{env.TLS_CLIENT_SNI}}"); + patch.replace("/bindings/tls_client0/options/alpn/0", "${{env.TLS_CLIENT_ALPN}}"); + // client vault + patch.replace("/vaults/client/options/trust/store", "${{env.TRUSTSTORE_PATH}}"); + patch.replace("/vaults/client/options/trust/type", "${{env.TRUSTSTORE_TYPE}}"); + patch.replace("/vaults/client/options/trust/password", "${{env.TRUSTSTORE_PASSWORD}}"); + // server vault + patch.replace("/vaults/server/options/keys/store", "${{env.KEYSTORE_PATH}}"); + patch.replace("/vaults/server/options/keys/type", "${{env.KEYSTORE_TYPE}}"); + patch.replace("/vaults/server/options/keys/password", "${{env.KEYSTORE_PASSWORD}}"); + } + + return patch.build(); + } + + private List unquotedEnvVars() + { + return List.of("TCP_CLIENT_PORT"); + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/AsyncApi.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/AsyncApi.java new file mode 100644 index 0000000000..512addcdea --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/AsyncApi.java @@ -0,0 +1,25 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +import java.util.Map; + +public class AsyncApi +{ + public Map servers; + public Map channels; + public Map operations; + public Components components; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Binding.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Binding.java new file mode 100644 index 0000000000..b008294c42 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Binding.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +public class Binding +{ + public String method; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Channel.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Channel.java new file mode 100644 index 0000000000..990dadf0fc --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Channel.java @@ -0,0 +1,25 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +import jakarta.json.bind.annotation.JsonbProperty; + +public class Channel +{ + public String address; + + @JsonbProperty("$ref") + public String ref; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Components.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Components.java new file mode 100644 index 0000000000..c138c91af3 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Components.java @@ -0,0 +1,25 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +import java.util.Map; + +import io.aklivity.zilla.runtime.command.config.internal.openapi.model.SecurityScheme; + +public class Components +{ + public Map securitySchemes; + public Map messages; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Item.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Item.java new file mode 100644 index 0000000000..05ad9b5d35 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Item.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +public class Item +{ + public String description; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Message.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Message.java new file mode 100644 index 0000000000..c73553c3b6 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Message.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +public class Message +{ + public Schema headers; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Operation.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Operation.java new file mode 100644 index 0000000000..8bf99ce810 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Operation.java @@ -0,0 +1,23 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +import java.util.Map; + +public class Operation +{ + public Map bindings; + public Channel channel; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Schema.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Schema.java new file mode 100644 index 0000000000..e05ef9ab7d --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Schema.java @@ -0,0 +1,22 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +import java.util.Map; + +public class Schema +{ + public Map properties; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/SecurityScheme.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/SecurityScheme.java new file mode 100644 index 0000000000..c57c946e63 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/SecurityScheme.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +public class SecurityScheme +{ + public String bearerFormat; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Server.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Server.java new file mode 100644 index 0000000000..eed9d65dc4 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/model/Server.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + +import java.util.List; +import java.util.Map; + +public class Server +{ + public String host; + public List>> security; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/AsyncApiMqttProxyConfigGenerator.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/AsyncApiMqttProxyConfigGenerator.java new file mode 100644 index 0000000000..e8c0e7cd18 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/AsyncApiMqttProxyConfigGenerator.java @@ -0,0 +1,344 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.mqtt.proxy; + +import static io.aklivity.zilla.runtime.engine.config.KindConfig.CLIENT; +import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; +import static java.util.Objects.requireNonNull; +import static org.agrona.LangUtil.rethrowUnchecked; + +import java.io.InputStream; +import java.net.URI; +import java.util.List; +import java.util.Map; + +import jakarta.json.Json; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; + +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttConditionConfig; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfig; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfig; +import io.aklivity.zilla.runtime.command.config.internal.airline.ConfigGenerator; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.AsyncApi; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.Channel; +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.view.ServerView; +import io.aklivity.zilla.runtime.engine.config.BindingConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.ConfigWriter; +import io.aklivity.zilla.runtime.engine.config.NamespaceConfig; +import io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; + +public class AsyncApiMqttProxyConfigGenerator extends ConfigGenerator +{ + private final InputStream inputStream; + + private AsyncApi asyncApi; + private int[] allPorts; + private int[] mqttPorts; + private int[] mqttsPorts; + private boolean isPlainEnabled; + private boolean isTlsEnabled; + + public AsyncApiMqttProxyConfigGenerator( + InputStream input) + { + this.inputStream = input; + } + + @Override + public String generate() + { + this.asyncApi = parseAsyncApi(inputStream); + this.allPorts = resolveAllPorts(); + this.mqttPorts = resolvePortsForScheme("mqtt"); + this.mqttsPorts = resolvePortsForScheme("mqtts"); + this.isPlainEnabled = mqttPorts != null; + this.isTlsEnabled = mqttsPorts != null; + ConfigWriter configWriter = new ConfigWriter(null); + String yaml = configWriter.write(createNamespace(), createEnvVarsPatch()); + return unquoteEnvVars(yaml, unquotedEnvVars()); + } + + private AsyncApi parseAsyncApi( + InputStream inputStream) + { + AsyncApi asyncApi = null; + try (Jsonb jsonb = JsonbBuilder.create()) + { + asyncApi = jsonb.fromJson(inputStream, AsyncApi.class); + } + catch (Exception ex) + { + rethrowUnchecked(ex); + } + return asyncApi; + } + + private int[] resolveAllPorts() + { + int[] ports = new int[asyncApi.servers.size()]; + String[] keys = asyncApi.servers.keySet().toArray(String[]::new); + for (int i = 0; i < asyncApi.servers.size(); i++) + { + ServerView server = ServerView.of(asyncApi.servers.get(keys[i])); + URI url = server.url(); + ports[i] = url.getPort(); + } + return ports; + } + + private int[] resolvePortsForScheme( + String scheme) + { + requireNonNull(scheme); + int[] ports = null; + URI url = findFirstServerUrlWithScheme(scheme); + if (url != null) + { + ports = new int[] {url.getPort()}; + } + return ports; + } + + private URI findFirstServerUrlWithScheme( + String scheme) + { + requireNonNull(scheme); + URI result = null; + for (String key : asyncApi.servers.keySet()) + { + ServerView server = ServerView.of(asyncApi.servers.get(key)); + if (scheme.equals(server.url().getScheme())) + { + result = server.url(); + break; + } + } + return result; + } + + private NamespaceConfig createNamespace() + { + return NamespaceConfig.builder() + .name("example") + .binding() + .name("tcp_server0") + .type("tcp") + .kind(SERVER) + .options(TcpOptionsConfig::builder) + .host("0.0.0.0") + .ports(allPorts) + .build() + .inject(this::injectPlainTcpRoute) + .inject(this::injectTlsTcpRoute) + .build() + .inject(this::injectTlsServer) + .binding() + .name("mqtt_server0") + .type("mqtt") + .kind(SERVER) + .inject(this::injectMqttServerRoutes) + .build() + .binding() + .name("mqtt_client0") + .type("mqtt") + .kind(CLIENT) + .exit(isTlsEnabled ? "tls_client0" : "tcp_client0") + .build() + .inject(this::injectTlsClient) + .binding() + .name("tcp_client0") + .type("tcp") + .kind(CLIENT) + .options(TcpOptionsConfig::builder) + .host("") // env + .ports(new int[]{0}) // env + .build() + .build() + .inject(this::injectVaults) + .build(); + } + + private BindingConfigBuilder> injectPlainTcpRoute( + BindingConfigBuilder> binding) + { + if (isPlainEnabled) + { + binding + .route() + .when(TcpConditionConfig::builder) + .ports(mqttPorts) + .build() + .exit("mqtt_server0") + .build(); + } + return binding; + } + + private BindingConfigBuilder> injectTlsTcpRoute( + BindingConfigBuilder> binding) + { + if (isTlsEnabled) + { + binding + .route() + .when(TcpConditionConfig::builder) + .ports(mqttsPorts) + .build() + .exit("tls_server0") + .build(); + } + return binding; + } + + private NamespaceConfigBuilder injectTlsServer( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .binding() + .name("tls_server0") + .type("tls") + .kind(SERVER) + .options(TlsOptionsConfig::builder) + .keys(List.of("")) // env + .sni(List.of("")) // env + .alpn(List.of("")) // env + .build() + .vault("server") + .exit("mqtt_server0") + .build(); + } + return namespace; + } + + private BindingConfigBuilder> injectMqttServerRoutes( + BindingConfigBuilder> binding) + { + for (Map.Entry entry : asyncApi.channels.entrySet()) + { + String topic = entry.getValue().address.replaceAll("\\{[^}]+\\}", "*"); + binding + .route() + .when(MqttConditionConfig::builder) + .publish() + .topic(topic) + .build() + .build() + .when(MqttConditionConfig::builder) + .subscribe() + .topic(topic) + .build() + .build() + .exit("mqtt_client0") + .build(); + } + return binding; + } + + private NamespaceConfigBuilder injectTlsClient( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .binding() + .name("tls_client0") + .type("tls") + .kind(CLIENT) + .options(TlsOptionsConfig::builder) + .trust(List.of("")) // env + .sni(List.of("")) // env + .alpn(List.of("")) // env + .trustcacerts(true) + .build() + .vault("client") + .exit("tcp_client0") + .build(); + } + return namespace; + } + + private NamespaceConfigBuilder injectVaults( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .vault() + .name("client") + .type("filesystem") + .options(FileSystemOptionsConfig::builder) + .trust() + .store("") // env + .type("") // env + .password("") // env + .build() + .build() + .build() + .vault() + .name("server") + .type("filesystem") + .options(FileSystemOptionsConfig::builder) + .keys() + .store("") // env + .type("") // env + .password("") //env + .build() + .build() + .build(); + } + return namespace; + } + + private JsonPatch createEnvVarsPatch() + { + JsonPatchBuilder patch = Json.createPatchBuilder(); + patch.replace("/bindings/tcp_client0/options/host", "${{env.TCP_CLIENT_HOST}}"); + patch.replace("/bindings/tcp_client0/options/port", "${{env.TCP_CLIENT_PORT}}"); + + if (isTlsEnabled) + { + // tls_server0 binding + patch.replace("/bindings/tls_server0/options/keys/0", "${{env.TLS_SERVER_KEY}}"); + patch.replace("/bindings/tls_server0/options/sni/0", "${{env.TLS_SERVER_SNI}}"); + patch.replace("/bindings/tls_server0/options/alpn/0", "${{env.TLS_SERVER_ALPN}}"); + // tls_client0 binding + patch.replace("/bindings/tls_client0/options/trust/0", "${{env.TLS_CLIENT_TRUST}}"); + patch.replace("/bindings/tls_client0/options/sni/0", "${{env.TLS_CLIENT_SNI}}"); + patch.replace("/bindings/tls_client0/options/alpn/0", "${{env.TLS_CLIENT_ALPN}}"); + // client vault + patch.replace("/vaults/client/options/trust/store", "${{env.TRUSTSTORE_PATH}}"); + patch.replace("/vaults/client/options/trust/type", "${{env.TRUSTSTORE_TYPE}}"); + patch.replace("/vaults/client/options/trust/password", "${{env.TRUSTSTORE_PASSWORD}}"); + // server vault + patch.replace("/vaults/server/options/keys/store", "${{env.KEYSTORE_PATH}}"); + patch.replace("/vaults/server/options/keys/type", "${{env.KEYSTORE_TYPE}}"); + patch.replace("/vaults/server/options/keys/password", "${{env.KEYSTORE_PASSWORD}}"); + } + + return patch.build(); + } + + private List unquotedEnvVars() + { + return List.of("TCP_CLIENT_PORT"); + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/ChannelView.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/ChannelView.java new file mode 100644 index 0000000000..a9b4832994 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/ChannelView.java @@ -0,0 +1,44 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.view; + +import java.util.Map; + +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.Channel; + +public final class ChannelView extends Resolvable +{ + private final Channel channel; + + private ChannelView( + Map channels, + Channel channel) + { + super(channels, "#/channels/(\\w+)"); + this.channel = channel.ref == null ? channel : resolveRef(channel.ref); + } + + public String address() + { + return channel.address; + } + + public static ChannelView of( + Map channels, + Channel channel) + { + return new ChannelView(channels, channel); + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/Resolvable.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/Resolvable.java new file mode 100644 index 0000000000..101dcfcb13 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/Resolvable.java @@ -0,0 +1,47 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.view; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class Resolvable +{ + private final Map map; + private final String regex; + + public Resolvable( + Map map, + String regex) + { + this.map = map; + this.regex = regex; + } + + protected T resolveRef( + String ref) + { + T result = null; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(ref); + if (matcher.matches()) + { + String key = matcher.group(1); + result = map.get(key); + } + return result; + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/ServerView.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/ServerView.java new file mode 100644 index 0000000000..b89742dc5f --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/view/ServerView.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.view; + +import java.net.URI; +import java.util.List; +import java.util.Map; + +import io.aklivity.zilla.runtime.command.config.internal.asyncapi.model.Server; + +public final class ServerView +{ + private final Server server; + + private ServerView( + Server server) + { + this.server = server; + } + + public URI url() + { + return URI.create(server.host); + } + + public List>> security() + { + return server.security; + } + + public String scheme() + { + return url().getScheme(); + } + + public String authority() + { + return String.format("%s:%d", url().getHost(), url().getPort()); + } + + public static ServerView of( + Server server) + { + return new ServerView(server); + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/OpenApiHttpProxyConfigGenerator.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/OpenApiHttpProxyConfigGenerator.java new file mode 100644 index 0000000000..a090a1ccaa --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/OpenApiHttpProxyConfigGenerator.java @@ -0,0 +1,471 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.http.proxy; + +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.CROSS_ORIGIN; +import static io.aklivity.zilla.runtime.engine.config.KindConfig.CLIENT; +import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; +import static java.util.Objects.requireNonNull; +import static org.agrona.LangUtil.rethrowUnchecked; + +import java.io.InputStream; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.json.Json; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; + +import io.aklivity.zilla.runtime.binding.http.config.HttpConditionConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfigBuilder; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfig; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfig; +import io.aklivity.zilla.runtime.command.config.internal.airline.ConfigGenerator; +import io.aklivity.zilla.runtime.command.config.internal.openapi.model.OpenApi; +import io.aklivity.zilla.runtime.command.config.internal.openapi.model.Server; +import io.aklivity.zilla.runtime.command.config.internal.openapi.view.PathView; +import io.aklivity.zilla.runtime.command.config.internal.openapi.view.ServerView; +import io.aklivity.zilla.runtime.engine.config.BindingConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.ConfigWriter; +import io.aklivity.zilla.runtime.engine.config.GuardedConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.NamespaceConfig; +import io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.RouteConfigBuilder; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; + +public class OpenApiHttpProxyConfigGenerator extends ConfigGenerator +{ + private final InputStream inputStream; + + private OpenApi openApi; + private int[] allPorts; + private int[] httpPorts; + private int[] httpsPorts; + private boolean isPlainEnabled; + private boolean isTlsEnabled; + private Map securitySchemes; + private boolean isJwtEnabled; + + public OpenApiHttpProxyConfigGenerator( + InputStream inputStream) + { + this.inputStream = inputStream; + } + + @Override + public String generate() + { + this.openApi = parseOpenApi(inputStream); + this.allPorts = resolveAllPorts(); + this.httpPorts = resolvePortsForScheme("http"); + this.httpsPorts = resolvePortsForScheme("https"); + this.isPlainEnabled = httpPorts != null; + this.isTlsEnabled = httpsPorts != null; + this.securitySchemes = resolveSecuritySchemes(); + this.isJwtEnabled = !securitySchemes.isEmpty(); + ConfigWriter configWriter = new ConfigWriter(null); + String yaml = configWriter.write(createNamespace(), createEnvVarsPatch()); + return unquoteEnvVars(yaml, unquotedEnvVars()); + } + + private OpenApi parseOpenApi( + InputStream inputStream) + { + OpenApi openApi = null; + try (Jsonb jsonb = JsonbBuilder.create()) + { + openApi = jsonb.fromJson(inputStream, OpenApi.class); + } + catch (Exception ex) + { + rethrowUnchecked(ex); + } + return openApi; + } + + private int[] resolveAllPorts() + { + int[] ports = new int[openApi.servers.size()]; + for (int i = 0; i < openApi.servers.size(); i++) + { + ServerView server = ServerView.of(openApi.servers.get(i)); + URI url = server.url(); + ports[i] = url.getPort(); + } + return ports; + } + + private int[] resolvePortsForScheme( + String scheme) + { + requireNonNull(scheme); + int[] ports = null; + URI url = findFirstServerUrlWithScheme(scheme); + if (url != null) + { + ports = new int[] {url.getPort()}; + } + return ports; + } + + private URI findFirstServerUrlWithScheme( + String scheme) + { + requireNonNull(scheme); + URI result = null; + for (Server item : openApi.servers) + { + ServerView server = ServerView.of(item); + if (scheme.equals(server.url().getScheme())) + { + result = server.url(); + break; + } + } + return result; + } + + private Map resolveSecuritySchemes() + { + requireNonNull(openApi); + Map result = new HashMap<>(); + if (openApi.components != null && openApi.components.securitySchemes != null) + { + for (String securitySchemeName : openApi.components.securitySchemes.keySet()) + { + String guardType = openApi.components.securitySchemes.get(securitySchemeName).bearerFormat; + if ("jwt".equals(guardType)) + { + result.put(securitySchemeName, guardType); + } + } + } + return result; + } + + private NamespaceConfig createNamespace() + { + return NamespaceConfig.builder() + .name("example") + .binding() + .name("tcp_server0") + .type("tcp") + .kind(SERVER) + .options(TcpOptionsConfig::builder) + .host("0.0.0.0") + .ports(allPorts) + .build() + .inject(this::injectPlainTcpRoute) + .inject(this::injectTlsTcpRoute) + .build() + .inject(this::injectTlsServer) + .binding() + .name("http_server0") + .type("http") + .kind(SERVER) + .options(HttpOptionsConfig::builder) + .access() + .policy(CROSS_ORIGIN) + .build() + .inject(this::injectHttpServerOptions) + .build() + .inject(this::injectHttpServerRoutes) + .build() + .binding() + .name("http_client0") + .type("http") + .kind(CLIENT) + .exit(isTlsEnabled ? "tls_client0" : "tcp_client0") + .build() + .inject(this::injectTlsClient) + .binding() + .name("tcp_client0") + .type("tcp") + .kind(CLIENT) + .options(TcpOptionsConfig::builder) + .host("") // env + .ports(new int[]{0}) // env + .build() + .build() + .inject(this::injectGuard) + .inject(this::injectVaults) + .build(); + } + + private BindingConfigBuilder> injectPlainTcpRoute( + BindingConfigBuilder> binding) + { + if (isPlainEnabled) + { + binding + .route() + .when(TcpConditionConfig::builder) + .ports(httpPorts) + .build() + .exit("http_server0") + .build(); + } + return binding; + } + + private BindingConfigBuilder> injectTlsTcpRoute( + BindingConfigBuilder> binding) + { + if (isTlsEnabled) + { + binding + .route() + .when(TcpConditionConfig::builder) + .ports(httpsPorts) + .build() + .exit("tls_server0") + .build(); + } + return binding; + } + + private NamespaceConfigBuilder injectTlsServer( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .binding() + .name("tls_server0") + .type("tls") + .kind(SERVER) + .options(TlsOptionsConfig::builder) + .keys(List.of("")) // env + .sni(List.of("")) // env + .alpn(List.of("")) // env + .build() + .vault("server") + .exit("http_server0") + .build(); + } + return namespace; + } + + private HttpOptionsConfigBuilder>> injectHttpServerOptions( + HttpOptionsConfigBuilder>> options) + { + if (isJwtEnabled) + { + options + .authorization() + .name("jwt0") + .credentials() + .header() + .name("authorization") + .pattern("Bearer {credentials}") + .build() + .build() + .build(); + } + return options; + } + + private BindingConfigBuilder> injectHttpServerRoutes( + BindingConfigBuilder> binding) + { + for (String item : openApi.paths.keySet()) + { + PathView path = PathView.of(openApi.paths.get(item)); + for (String method : path.methods().keySet()) + { + binding + .route() + .exit("http_client0") + .when(HttpConditionConfig::builder) + .header(":path", item.replaceAll("\\{[^}]+\\}", "*")) + .header(":method", method) + .build() + .inject(route -> injectHttpServerRouteGuarded(route, path, method)) + .build(); + } + } + return binding; + } + + private RouteConfigBuilder>> injectHttpServerRouteGuarded( + RouteConfigBuilder>> route, + PathView path, + String method) + { + List>> security = path.methods().get(method).security; + if (security != null) + { + for (Map> securityItem : security) + { + for (String securityItemLabel : securityItem.keySet()) + { + if (isJwtEnabled && "jwt".equals(securitySchemes.get(securityItemLabel))) + { + route + .guarded() + .name("jwt0") + .inject(guarded -> injectGuardedRoles(guarded, securityItem.get(securityItemLabel))) + .build(); + } + } + } + } + return route; + } + + private GuardedConfigBuilder injectGuardedRoles( + GuardedConfigBuilder guarded, + List roles) + { + for (String role : roles) + { + guarded.role(role); + } + return guarded; + } + + private NamespaceConfigBuilder injectTlsClient( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .binding() + .name("tls_client0") + .type("tls") + .kind(CLIENT) + .options(TlsOptionsConfig::builder) + .trust(List.of("")) // env + .sni(List.of("")) // env + .alpn(List.of("")) // env + .trustcacerts(true) + .build() + .vault("client") + .exit("tcp_client0") + .build(); + } + return namespace; + } + + private NamespaceConfigBuilder injectGuard( + NamespaceConfigBuilder namespace) + { + if (isJwtEnabled) + { + namespace + .guard() + .name("jwt0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .issuer("") // env + .audience("") // env + .key() + .alg("").kty("").kid("").use("").n("").e("").crv("").x("").y("") // env + .build() + .build() + .build(); + } + return namespace; + } + + private NamespaceConfigBuilder injectVaults( + NamespaceConfigBuilder namespace) + { + if (isTlsEnabled) + { + namespace + .vault() + .name("client") + .type("filesystem") + .options(FileSystemOptionsConfig::builder) + .trust() + .store("") // env + .type("") // env + .password("") // env + .build() + .build() + .build() + .vault() + .name("server") + .type("filesystem") + .options(FileSystemOptionsConfig::builder) + .keys() + .store("") // env + .type("") // env + .password("") //env + .build() + .build() + .build(); + } + return namespace; + } + + private JsonPatch createEnvVarsPatch() + { + JsonPatchBuilder patch = Json.createPatchBuilder(); + patch.replace("/bindings/tcp_client0/options/host", "${{env.TCP_CLIENT_HOST}}"); + patch.replace("/bindings/tcp_client0/options/port", "${{env.TCP_CLIENT_PORT}}"); + + if (isJwtEnabled) + { + // jwt0 guard + patch.replace("/guards/jwt0/options/issuer", "${{env.JWT_ISSUER}}"); + patch.replace("/guards/jwt0/options/audience", "${{env.JWT_AUDIENCE}}"); + patch.replace("/guards/jwt0/options/keys/0/alg", "${{env.JWT_ALG}}"); + patch.replace("/guards/jwt0/options/keys/0/kty", "${{env.JWT_KTY}}"); + patch.replace("/guards/jwt0/options/keys/0/kid", "${{env.JWT_KID}}"); + patch.replace("/guards/jwt0/options/keys/0/use", "${{env.JWT_USE}}"); + patch.replace("/guards/jwt0/options/keys/0/n", "${{env.JWT_N}}"); + patch.replace("/guards/jwt0/options/keys/0/e", "${{env.JWT_E}}"); + patch.replace("/guards/jwt0/options/keys/0/crv", "${{env.JWT_CRV}}"); + patch.replace("/guards/jwt0/options/keys/0/x", "${{env.JWT_X}}"); + patch.replace("/guards/jwt0/options/keys/0/y", "${{env.JWT_Y}}"); + } + + if (isTlsEnabled) + { + // tls_server0 binding + patch.replace("/bindings/tls_server0/options/keys/0", "${{env.TLS_SERVER_KEY}}"); + patch.replace("/bindings/tls_server0/options/sni/0", "${{env.TLS_SERVER_SNI}}"); + patch.replace("/bindings/tls_server0/options/alpn/0", "${{env.TLS_SERVER_ALPN}}"); + // tls_client0 binding + patch.replace("/bindings/tls_client0/options/trust/0", "${{env.TLS_CLIENT_TRUST}}"); + patch.replace("/bindings/tls_client0/options/sni/0", "${{env.TLS_CLIENT_SNI}}"); + patch.replace("/bindings/tls_client0/options/alpn/0", "${{env.TLS_CLIENT_ALPN}}"); + // client vault + patch.replace("/vaults/client/options/trust/store", "${{env.TRUSTSTORE_PATH}}"); + patch.replace("/vaults/client/options/trust/type", "${{env.TRUSTSTORE_TYPE}}"); + patch.replace("/vaults/client/options/trust/password", "${{env.TRUSTSTORE_PASSWORD}}"); + // server vault + patch.replace("/vaults/server/options/keys/store", "${{env.KEYSTORE_PATH}}"); + patch.replace("/vaults/server/options/keys/type", "${{env.KEYSTORE_TYPE}}"); + patch.replace("/vaults/server/options/keys/password", "${{env.KEYSTORE_PASSWORD}}"); + } + + return patch.build(); + } + + private List unquotedEnvVars() + { + return List.of("TCP_CLIENT_PORT"); + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/BearerAuth.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/BearerAuth.java new file mode 100644 index 0000000000..cc5224c3ad --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/BearerAuth.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.model; + +public class BearerAuth +{ + public String bearerFormat; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Components.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Components.java new file mode 100644 index 0000000000..ba0ad10db6 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Components.java @@ -0,0 +1,22 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.model; + +import java.util.Map; + +public class Components +{ + public Map securitySchemes; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/OpenApi.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/OpenApi.java new file mode 100644 index 0000000000..042f3173a5 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/OpenApi.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.model; + +import java.util.LinkedHashMap; +import java.util.List; + +public class OpenApi +{ + public String openapi; + public List servers; + public LinkedHashMap paths; + public Components components; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Operation.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Operation.java new file mode 100644 index 0000000000..c877e5dc85 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Operation.java @@ -0,0 +1,23 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.model; + +import java.util.List; +import java.util.Map; + +public class Operation +{ + public List>> security; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/PathItem.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/PathItem.java new file mode 100644 index 0000000000..7235334d61 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/PathItem.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.model; + +public class PathItem +{ + public Operation get; + public Operation put; + public Operation post; + public Operation delete; + public Operation options; + public Operation head; + public Operation patch; + public Operation trace; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/SecurityScheme.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/SecurityScheme.java new file mode 100644 index 0000000000..31be12fcdb --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/SecurityScheme.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.model; + +public class SecurityScheme +{ + public String bearerFormat; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Server.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Server.java new file mode 100644 index 0000000000..0d9072e758 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/model/Server.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.model; + +public class Server +{ + public String url; +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/view/PathView.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/view/PathView.java new file mode 100644 index 0000000000..f286508307 --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/view/PathView.java @@ -0,0 +1,62 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.view; + +import java.util.LinkedHashMap; +import java.util.Map; + +import io.aklivity.zilla.runtime.command.config.internal.openapi.model.Operation; +import io.aklivity.zilla.runtime.command.config.internal.openapi.model.PathItem; + +public class PathView +{ + private final LinkedHashMap methods; + + public PathView( + PathItem pathItem) + { + this.methods = new LinkedHashMap<>(); + putIfNotNull(methods, "GET", pathItem.get); + putIfNotNull(methods, "PUT", pathItem.put); + putIfNotNull(methods, "POST", pathItem.post); + putIfNotNull(methods, "DELETE", pathItem.delete); + putIfNotNull(methods, "OPTIONS", pathItem.options); + putIfNotNull(methods, "HEAD", pathItem.head); + putIfNotNull(methods, "PATCH", pathItem.patch); + putIfNotNull(methods, "TRACE", pathItem.trace); + } + + public Map methods() + { + return methods; + } + + public static PathView of( + PathItem pathItem) + { + return new PathView(pathItem); + } + + private static void putIfNotNull( + Map methods, + String method, + Operation operation) + { + if (operation != null) + { + methods.put(method, operation); + } + } +} diff --git a/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/view/ServerView.java b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/view/ServerView.java new file mode 100644 index 0000000000..4d028a170e --- /dev/null +++ b/incubator/command-config/src/main/java/io/aklivity/zilla/runtime/command/config/internal/openapi/view/ServerView.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.view; + +import java.net.URI; + +import io.aklivity.zilla.runtime.command.config.internal.openapi.model.Server; + +public final class ServerView +{ + private URI url; + + private ServerView( + Server server) + { + this.url = URI.create(server.url); + } + + public URI url() + { + return url; + } + + public static ServerView of( + Server server) + { + return new ServerView(server); + } +} diff --git a/incubator/command-config/src/main/moditect/module-info.java b/incubator/command-config/src/main/moditect/module-info.java new file mode 100644 index 0000000000..ec140c6d79 --- /dev/null +++ b/incubator/command-config/src/main/moditect/module-info.java @@ -0,0 +1,35 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +module io.aklivity.zilla.runtime.command.config +{ + requires io.aklivity.zilla.runtime.command; + requires io.aklivity.zilla.runtime.engine; + requires io.aklivity.zilla.runtime.binding.http; + requires io.aklivity.zilla.runtime.binding.mqtt; + requires io.aklivity.zilla.runtime.binding.tcp; + requires io.aklivity.zilla.runtime.binding.tls; + requires io.aklivity.zilla.runtime.guard.jwt; + requires io.aklivity.zilla.runtime.vault.filesystem; + + opens io.aklivity.zilla.runtime.command.config.internal.airline + to com.github.rvesse.airline; + + opens io.aklivity.zilla.runtime.command.config.internal.openapi.model; + + opens io.aklivity.zilla.runtime.command.config.internal.asyncapi.model; + + provides io.aklivity.zilla.runtime.command.ZillaCommandSpi + with io.aklivity.zilla.runtime.command.config.internal.ZillaConfigCommandSpi; +} diff --git a/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/AsyncApiHttpProxyConfigGeneratorTest.java b/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/AsyncApiHttpProxyConfigGeneratorTest.java new file mode 100644 index 0000000000..8618b39a45 --- /dev/null +++ b/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/AsyncApiHttpProxyConfigGeneratorTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.http.proxy; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class AsyncApiHttpProxyConfigGeneratorTest +{ + @Test + public void shouldGeneratePlainConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("plain/asyncapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("plain/zilla.yaml").getFile())); + AsyncApiHttpProxyConfigGenerator generator = new AsyncApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateJwtConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("jwt/asyncapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("jwt/zilla.yaml").getFile())); + AsyncApiHttpProxyConfigGenerator generator = new AsyncApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateTlsConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("tls/asyncapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("tls/zilla.yaml").getFile())); + AsyncApiHttpProxyConfigGenerator generator = new AsyncApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateCompleteConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("complete/asyncapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("complete/zilla.yaml").getFile())); + AsyncApiHttpProxyConfigGenerator generator = new AsyncApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } +} diff --git a/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/AsyncApiMqttProxyConfigGeneratorTest.java b/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/AsyncApiMqttProxyConfigGeneratorTest.java new file mode 100644 index 0000000000..56ef3aaf4e --- /dev/null +++ b/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/AsyncApiMqttProxyConfigGeneratorTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.asyncapi.mqtt.proxy; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class AsyncApiMqttProxyConfigGeneratorTest +{ + @Test + public void shouldGeneratePlainConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("plain/asyncapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("plain/zilla.yaml").getFile())); + AsyncApiMqttProxyConfigGenerator generator = new AsyncApiMqttProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateTlsConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("tls/asyncapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("tls/zilla.yaml").getFile())); + AsyncApiMqttProxyConfigGenerator generator = new AsyncApiMqttProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateCompleteConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("complete/asyncapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("complete/zilla.yaml").getFile())); + AsyncApiMqttProxyConfigGenerator generator = new AsyncApiMqttProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } +} diff --git a/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/OpenApiHttpProxyConfigGeneratorTest.java b/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/OpenApiHttpProxyConfigGeneratorTest.java new file mode 100644 index 0000000000..dd56ca1e5e --- /dev/null +++ b/incubator/command-config/src/test/java/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/OpenApiHttpProxyConfigGeneratorTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.command.config.internal.openapi.http.proxy; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class OpenApiHttpProxyConfigGeneratorTest +{ + @Test + public void shouldGeneratePlainConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("plain/openapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("plain/zilla.yaml").getFile())); + OpenApiHttpProxyConfigGenerator generator = new OpenApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateJwtConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("jwt/openapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("jwt/zilla.yaml").getFile())); + OpenApiHttpProxyConfigGenerator generator = new OpenApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateTlsConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("tls/openapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("tls/zilla.yaml").getFile())); + OpenApiHttpProxyConfigGenerator generator = new OpenApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } + + @Test + public void shouldGenerateCompleteConfig() throws Exception + { + try (InputStream inputStream = getClass().getResourceAsStream("complete/openapi.yaml")) + { + // GIVEN + String expectedResult = Files.readString(Path.of(getClass().getResource("complete/zilla.yaml").getFile())); + OpenApiHttpProxyConfigGenerator generator = new OpenApiHttpProxyConfigGenerator(inputStream); + + // WHEN + String result = generator.generate(); + + // THEN + assertThat(result, equalTo(expectedResult)); + } + } +} diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/complete/asyncapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/complete/asyncapi.yaml new file mode 100644 index 0000000000..d2e61e7de5 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/complete/asyncapi.yaml @@ -0,0 +1,98 @@ +asyncapi: 3.0.0 +info: + title: HTTP Zilla Proxy + version: 1.0.0 + license: + name: Aklivity Community License +servers: + secure: + host: https://localhost:9090 + protocol: http + protocolVersion: '1.1' + security: + - httpBearerToken: + - public + plain: + host: http://localhost:8080 + protocol: http + protocolVersion: '1.1' +defaultContentType: application/json + +channels: + items: + address: /items + messages: + items: + $ref: '#/components/messages/item' + itemsbyid: + address: /items/{id} + parameters: + id: + description: Event ID. + schema: + type: string + messages: + items: + $ref: '#/components/messages/item' + +operations: + postEvents: + action: send + bindings: + http: + type: request + method: POST + channel: + $ref: '#/channels/items' + getEvents: + action: receive + bindings: + http: + type: request + method: GET + query: + type: object + properties: + limit: + type: number + channel: + $ref: '#/channels/itemsbyid' + +components: + correlationIds: + itemsCorrelationId: + location: '$message.header#/idempotency-key' + messages: + item: + name: event + title: An event + correlationId: + $ref: "#/components/correlationIds/itemsCorrelationId" + headers: + type: object + properties: + idempotency-key: + description: Unique identifier for a given event + type: string + authorization: + description: Bearer {credentials} + type: string + contentType: application/json + payload: + type: object + properties: + item: + $ref: "#/components/schemas/item" + schemas: + item: + type: object + properties: + greeting: + type: string + required: + - greeting + securitySchemes: + httpBearerToken: + type: http + scheme: bearer + bearerFormat: jwt diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/complete/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/complete/zilla.yaml new file mode 100644 index 0000000000..acce74ba53 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/complete/zilla.yaml @@ -0,0 +1,129 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: + - 8080 + - 9090 + routes: + - exit: http_server0 + when: + - port: 8080 + - exit: tls_server0 + when: + - port: 9090 + tls_server0: + vault: server + type: tls + kind: server + options: + keys: + - "${{env.TLS_SERVER_KEY}}" + sni: + - "${{env.TLS_SERVER_SNI}}" + alpn: + - "${{env.TLS_SERVER_ALPN}}" + exit: http_server0 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + authorization: + jwt0: + credentials: + headers: + authorization: "Bearer {credentials}" + routes: + - exit: http_client0 + when: + - headers: + :scheme: http + :authority: localhost:8080 + :path: /items/* + :method: GET + - exit: http_client0 + when: + - headers: + :scheme: http + :authority: localhost:8080 + :path: /items + :method: POST + - exit: http_client0 + when: + - headers: + :scheme: https + :authority: localhost:9090 + :path: /items/* + :method: GET + guarded: + jwt0: + - public + - exit: http_client0 + when: + - headers: + :scheme: https + :authority: localhost:9090 + :path: /items + :method: POST + guarded: + jwt0: + - public + http_client0: + type: http + kind: client + exit: tls_client0 + tls_client0: + vault: client + type: tls + kind: client + options: + trust: + - "${{env.TLS_CLIENT_TRUST}}" + trustcacerts: true + sni: + - "${{env.TLS_CLIENT_SNI}}" + alpn: + - "${{env.TLS_CLIENT_ALPN}}" + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +guards: + jwt0: + type: jwt + options: + issuer: "${{env.JWT_ISSUER}}" + audience: "${{env.JWT_AUDIENCE}}" + keys: + - kty: "${{env.JWT_KTY}}" + "n": "${{env.JWT_N}}" + e: "${{env.JWT_E}}" + alg: "${{env.JWT_ALG}}" + crv: "${{env.JWT_CRV}}" + x: "${{env.JWT_X}}" + "y": "${{env.JWT_Y}}" + use: "${{env.JWT_USE}}" + kid: "${{env.JWT_KID}}" +vaults: + client: + type: filesystem + options: + trust: + store: "${{env.TRUSTSTORE_PATH}}" + type: "${{env.TRUSTSTORE_TYPE}}" + password: "${{env.TRUSTSTORE_PASSWORD}}" + server: + type: filesystem + options: + keys: + store: "${{env.KEYSTORE_PATH}}" + type: "${{env.KEYSTORE_TYPE}}" + password: "${{env.KEYSTORE_PASSWORD}}" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/jwt/asyncapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/jwt/asyncapi.yaml new file mode 100644 index 0000000000..5be0904148 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/jwt/asyncapi.yaml @@ -0,0 +1,94 @@ +asyncapi: 3.0.0 +info: + title: HTTP Zilla Proxy + version: 1.0.0 + license: + name: Aklivity Community License +servers: + plain: + host: http://localhost:8080 + protocol: http + protocolVersion: '1.1' + security: + - httpBearerToken: + - public +defaultContentType: application/json + +channels: + items: + address: /items + messages: + items: + $ref: '#/components/messages/item' + itemsbyid: + address: /items/{id} + parameters: + id: + description: Event ID. + schema: + type: string + messages: + items: + $ref: '#/components/messages/item' + +operations: + postEvents: + action: send + bindings: + http: + type: request + method: POST + channel: + $ref: '#/channels/items' + getEvents: + action: receive + bindings: + http: + type: request + method: GET + query: + type: object + properties: + limit: + type: number + channel: + $ref: '#/channels/itemsbyid' + +components: + correlationIds: + itemsCorrelationId: + location: '$message.header#/idempotency-key' + messages: + item: + name: event + title: An event + correlationId: + $ref: "#/components/correlationIds/itemsCorrelationId" + headers: + type: object + properties: + idempotency-key: + description: Unique identifier for a given event + type: string + authorization: + description: Bearer {credentials} + type: string + contentType: application/json + payload: + type: object + properties: + item: + $ref: "#/components/schemas/item" + schemas: + item: + type: object + properties: + greeting: + type: string + required: + - greeting + securitySchemes: + httpBearerToken: + type: http + scheme: bearer + bearerFormat: jwt diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/jwt/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/jwt/zilla.yaml new file mode 100644 index 0000000000..880a24f184 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/jwt/zilla.yaml @@ -0,0 +1,70 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 8080 + routes: + - exit: http_server0 + when: + - port: 8080 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + authorization: + jwt0: + credentials: + headers: + authorization: "Bearer {credentials}" + routes: + - exit: http_client0 + when: + - headers: + :scheme: http + :authority: localhost:8080 + :path: /items/* + :method: GET + guarded: + jwt0: + - public + - exit: http_client0 + when: + - headers: + :scheme: http + :authority: localhost:8080 + :path: /items + :method: POST + guarded: + jwt0: + - public + http_client0: + type: http + kind: client + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +guards: + jwt0: + type: jwt + options: + issuer: "${{env.JWT_ISSUER}}" + audience: "${{env.JWT_AUDIENCE}}" + keys: + - kty: "${{env.JWT_KTY}}" + "n": "${{env.JWT_N}}" + e: "${{env.JWT_E}}" + alg: "${{env.JWT_ALG}}" + crv: "${{env.JWT_CRV}}" + x: "${{env.JWT_X}}" + "y": "${{env.JWT_Y}}" + use: "${{env.JWT_USE}}" + kid: "${{env.JWT_KID}}" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/plain/asyncapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/plain/asyncapi.yaml new file mode 100644 index 0000000000..e5b6e54ced --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/plain/asyncapi.yaml @@ -0,0 +1,83 @@ +asyncapi: 3.0.0 +info: + title: HTTP Zilla Proxy + version: 1.0.0 + license: + name: Aklivity Community License +servers: + plain: + host: http://localhost:8080 + protocol: http + protocolVersion: '1.1' +defaultContentType: application/json + +channels: + items: + address: /items + messages: + items: + $ref: '#/components/messages/item' + itemsbyid: + address: /items/{id} + parameters: + id: + description: Event ID. + schema: + type: string + messages: + items: + $ref: '#/components/messages/item' + +operations: + postEvents: + action: send + bindings: + http: + type: request + method: POST + channel: + $ref: '#/channels/items' + getEvents: + action: receive + bindings: + http: + type: request + method: GET + query: + type: object + properties: + limit: + type: number + channel: + $ref: '#/channels/itemsbyid' + +components: + correlationIds: + itemsCorrelationId: + location: '$message.header#/idempotency-key' + messages: + item: + name: event + title: An event + correlationId: + $ref: "#/components/correlationIds/itemsCorrelationId" + headers: + type: object + properties: + idempotency-key: + description: Unique identifier for a given event + type: string + contentType: application/json + payload: + type: object + properties: + item: + $ref: "#/components/schemas/item" + schemas: + item: + type: object + properties: + greeting: + type: string + required: + - greeting diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/plain/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/plain/zilla.yaml new file mode 100644 index 0000000000..d1ff8a09cd --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/plain/zilla.yaml @@ -0,0 +1,43 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 8080 + routes: + - exit: http_server0 + when: + - port: 8080 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + routes: + - exit: http_client0 + when: + - headers: + :scheme: http + :authority: localhost:8080 + :path: /items/* + :method: GET + - exit: http_client0 + when: + - headers: + :scheme: http + :authority: localhost:8080 + :path: /items + :method: POST + http_client0: + type: http + kind: client + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/tls/asyncapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/tls/asyncapi.yaml new file mode 100644 index 0000000000..eadce1aeb7 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/tls/asyncapi.yaml @@ -0,0 +1,83 @@ +asyncapi: 3.0.0 +info: + title: HTTP Zilla Proxy + version: 1.0.0 + license: + name: Aklivity Community License +servers: + secure: + host: https://localhost:9090 + protocol: http + protocolVersion: '1.1' +defaultContentType: application/json + +channels: + items: + address: /items + messages: + items: + $ref: '#/components/messages/item' + itemsbyid: + address: /items/{id} + parameters: + id: + description: Event ID. + schema: + type: string + messages: + items: + $ref: '#/components/messages/item' + +operations: + postEvents: + action: send + bindings: + http: + type: request + method: POST + channel: + $ref: '#/channels/items' + getEvents: + action: receive + bindings: + http: + type: request + method: GET + query: + type: object + properties: + limit: + type: number + channel: + $ref: '#/channels/itemsbyid' + +components: + correlationIds: + itemsCorrelationId: + location: '$message.header#/idempotency-key' + messages: + item: + name: event + title: An event + correlationId: + $ref: "#/components/correlationIds/itemsCorrelationId" + headers: + type: object + properties: + idempotency-key: + description: Unique identifier for a given event + type: string + contentType: application/json + payload: + type: object + properties: + item: + $ref: "#/components/schemas/item" + schemas: + item: + type: object + properties: + greeting: + type: string + required: + - greeting diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/tls/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/tls/zilla.yaml new file mode 100644 index 0000000000..7b4138fbe0 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/http/proxy/tls/zilla.yaml @@ -0,0 +1,83 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 9090 + routes: + - exit: tls_server0 + when: + - port: 9090 + tls_server0: + vault: server + type: tls + kind: server + options: + keys: + - "${{env.TLS_SERVER_KEY}}" + sni: + - "${{env.TLS_SERVER_SNI}}" + alpn: + - "${{env.TLS_SERVER_ALPN}}" + exit: http_server0 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + routes: + - exit: http_client0 + when: + - headers: + :scheme: https + :authority: localhost:9090 + :path: /items/* + :method: GET + - exit: http_client0 + when: + - headers: + :scheme: https + :authority: localhost:9090 + :path: /items + :method: POST + http_client0: + type: http + kind: client + exit: tls_client0 + tls_client0: + vault: client + type: tls + kind: client + options: + trust: + - "${{env.TLS_CLIENT_TRUST}}" + trustcacerts: true + sni: + - "${{env.TLS_CLIENT_SNI}}" + alpn: + - "${{env.TLS_CLIENT_ALPN}}" + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +vaults: + client: + type: filesystem + options: + trust: + store: "${{env.TRUSTSTORE_PATH}}" + type: "${{env.TRUSTSTORE_TYPE}}" + password: "${{env.TRUSTSTORE_PASSWORD}}" + server: + type: filesystem + options: + keys: + store: "${{env.KEYSTORE_PATH}}" + type: "${{env.KEYSTORE_TYPE}}" + password: "${{env.KEYSTORE_PASSWORD}}" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/complete/asyncapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/complete/asyncapi.yaml new file mode 100644 index 0000000000..b3bbaceddf --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/complete/asyncapi.yaml @@ -0,0 +1,61 @@ +asyncapi: 3.0.0 +info: + title: Zilla MQTT Proxy + version: 1.0.0 + license: + name: Aklivity Community License +servers: + secure: + host: mqtts://localhost:8883 + protocol: secure-mqtt + plain: + host: mqtt://localhost:1883 + protocol: mqtt +defaultContentType: application/json + +channels: + smartylighting: + address: "smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured" + title: MQTT Topic to produce & consume topic. + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + messages: + items: + $ref: '#/components/messages/item' + +operations: + sendEvents: + action: send + channel: + $ref: '#/channels/smartylighting' + + receiveEvents: + action: receive + channel: + $ref: '#/channels/smartylighting' + +components: + parameters: + streetlightId: + description: Street Light ID + location: $message.header#/id + messages: + item: + name: event + title: An event + headers: + type: object + properties: + idempotency-key: + description: Unique identifier for a given event + type: string + id: + description: Street Light ID + type: string + contentType: application/json + payload: + type: object + properties: + item: + $ref: "#/components/schemas/item" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/complete/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/complete/zilla.yaml new file mode 100644 index 0000000000..619880a249 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/complete/zilla.yaml @@ -0,0 +1,77 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: + - 1883 + - 8883 + routes: + - exit: mqtt_server0 + when: + - port: 1883 + - exit: tls_server0 + when: + - port: 8883 + tls_server0: + vault: server + type: tls + kind: server + options: + keys: + - "${{env.TLS_SERVER_KEY}}" + sni: + - "${{env.TLS_SERVER_SNI}}" + alpn: + - "${{env.TLS_SERVER_ALPN}}" + exit: mqtt_server0 + mqtt_server0: + type: mqtt + kind: server + routes: + - exit: mqtt_client0 + when: + - publish: + - topic: smartylighting/streetlights/1/0/event/*/lighting/measured + - subscribe: + - topic: smartylighting/streetlights/1/0/event/*/lighting/measured + mqtt_client0: + type: mqtt + kind: client + exit: tls_client0 + tls_client0: + vault: client + type: tls + kind: client + options: + trust: + - "${{env.TLS_CLIENT_TRUST}}" + trustcacerts: true + sni: + - "${{env.TLS_CLIENT_SNI}}" + alpn: + - "${{env.TLS_CLIENT_ALPN}}" + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +vaults: + client: + type: filesystem + options: + trust: + store: "${{env.TRUSTSTORE_PATH}}" + type: "${{env.TRUSTSTORE_TYPE}}" + password: "${{env.TRUSTSTORE_PASSWORD}}" + server: + type: filesystem + options: + keys: + store: "${{env.KEYSTORE_PATH}}" + type: "${{env.KEYSTORE_TYPE}}" + password: "${{env.KEYSTORE_PASSWORD}}" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/plain/asyncapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/plain/asyncapi.yaml new file mode 100644 index 0000000000..57b918e490 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/plain/asyncapi.yaml @@ -0,0 +1,58 @@ +asyncapi: 3.0.0 +info: + title: Zilla MQTT Proxy + version: 1.0.0 + license: + name: Aklivity Community License +servers: + plain: + host: mqtt://localhost:1883 + protocol: mqtt +defaultContentType: application/json + +channels: + smartylighting: + address: "smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured" + title: MQTT Topic to produce & consume topic. + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + messages: + items: + $ref: '#/components/messages/item' + +operations: + sendEvents: + action: send + channel: + $ref: '#/channels/smartylighting' + + receiveEvents: + action: receive + channel: + $ref: '#/channels/smartylighting' + +components: + parameters: + streetlightId: + description: Street Light ID + location: $message.header#/id + messages: + item: + name: event + title: An event + headers: + type: object + properties: + idempotency-key: + description: Unique identifier for a given event + type: string + id: + description: Street Light ID + type: string + contentType: application/json + payload: + type: object + properties: + item: + $ref: "#/components/schemas/item" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/plain/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/plain/zilla.yaml new file mode 100644 index 0000000000..9ed3ffa917 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/plain/zilla.yaml @@ -0,0 +1,32 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 1883 + routes: + - exit: mqtt_server0 + when: + - port: 1883 + mqtt_server0: + type: mqtt + kind: server + routes: + - exit: mqtt_client0 + when: + - publish: + - topic: smartylighting/streetlights/1/0/event/*/lighting/measured + - subscribe: + - topic: smartylighting/streetlights/1/0/event/*/lighting/measured + mqtt_client0: + type: mqtt + kind: client + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/tls/asyncapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/tls/asyncapi.yaml new file mode 100644 index 0000000000..499d8926ff --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/tls/asyncapi.yaml @@ -0,0 +1,58 @@ +asyncapi: 3.0.0 +info: + title: Zilla MQTT Proxy + version: 1.0.0 + license: + name: Aklivity Community License +servers: + secure: + host: mqtts://localhost:8883 + protocol: secure-mqtt +defaultContentType: application/json + +channels: + smartylighting: + address: "smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured" + title: MQTT Topic to produce & consume topic. + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + messages: + items: + $ref: '#/components/messages/item' + +operations: + sendEvents: + action: send + channel: + $ref: '#/channels/smartylighting' + + receiveEvents: + action: receive + channel: + $ref: '#/channels/smartylighting' + +components: + parameters: + streetlightId: + description: Street Light ID + location: $message.header#/id + messages: + item: + name: event + title: An event + headers: + type: object + properties: + idempotency-key: + description: Unique identifier for a given event + type: string + id: + description: Street Light ID + type: string + contentType: application/json + payload: + type: object + properties: + item: + $ref: "#/components/schemas/item" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/tls/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/tls/zilla.yaml new file mode 100644 index 0000000000..f5046ffb0b --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/asyncapi/mqtt/proxy/tls/zilla.yaml @@ -0,0 +1,72 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 8883 + routes: + - exit: tls_server0 + when: + - port: 8883 + tls_server0: + vault: server + type: tls + kind: server + options: + keys: + - "${{env.TLS_SERVER_KEY}}" + sni: + - "${{env.TLS_SERVER_SNI}}" + alpn: + - "${{env.TLS_SERVER_ALPN}}" + exit: mqtt_server0 + mqtt_server0: + type: mqtt + kind: server + routes: + - exit: mqtt_client0 + when: + - publish: + - topic: smartylighting/streetlights/1/0/event/*/lighting/measured + - subscribe: + - topic: smartylighting/streetlights/1/0/event/*/lighting/measured + mqtt_client0: + type: mqtt + kind: client + exit: tls_client0 + tls_client0: + vault: client + type: tls + kind: client + options: + trust: + - "${{env.TLS_CLIENT_TRUST}}" + trustcacerts: true + sni: + - "${{env.TLS_CLIENT_SNI}}" + alpn: + - "${{env.TLS_CLIENT_ALPN}}" + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +vaults: + client: + type: filesystem + options: + trust: + store: "${{env.TRUSTSTORE_PATH}}" + type: "${{env.TRUSTSTORE_TYPE}}" + password: "${{env.TRUSTSTORE_PASSWORD}}" + server: + type: filesystem + options: + keys: + store: "${{env.KEYSTORE_PATH}}" + type: "${{env.KEYSTORE_TYPE}}" + password: "${{env.KEYSTORE_PASSWORD}}" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/complete/openapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/complete/openapi.yaml new file mode 100644 index 0000000000..cfb9abf2fc --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/complete/openapi.yaml @@ -0,0 +1,169 @@ +openapi: 3.1.0 +hello: $.openapi +info: + version: 1.0.0 + title: Zilla CRUD V1 + license: + name: Aklivity Community License +servers: + - url: http://localhost:8080 + - url: https://localhost:9090 +paths: + /items: + post: + summary: Create an item + operationId: createItem + tags: + - items + requestBody: + content: + 'application/json': + schema: + $ref: '#/components/schemas/Item' + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + security: + - bearerAuth: + - create:items + get: + summary: List all items + operationId: listItems + tags: + - items + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + maximum: 100 + format: int32 + responses: + '200': + description: A paged array of items + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Items" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + security: + - bearerAuth: + - list:items + /items/{id}: + get: + summary: Get an item + operationId: showItemById + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Item" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + put: + summary: Update an item by key + operationId: updateItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to update + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + delete: + summary: Delete an item by key + operationId: deleteItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to delete + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Item: + type: object + required: + - greeting + properties: + greeting: + type: string + tag: + type: string + Items: + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/Item" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: jwt diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/complete/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/complete/zilla.yaml new file mode 100644 index 0000000000..7cb3ade4ad --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/complete/zilla.yaml @@ -0,0 +1,126 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: + - 8080 + - 9090 + routes: + - exit: http_server0 + when: + - port: 8080 + - exit: tls_server0 + when: + - port: 9090 + tls_server0: + vault: server + type: tls + kind: server + options: + keys: + - "${{env.TLS_SERVER_KEY}}" + sni: + - "${{env.TLS_SERVER_SNI}}" + alpn: + - "${{env.TLS_SERVER_ALPN}}" + exit: http_server0 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + authorization: + jwt0: + credentials: + headers: + authorization: "Bearer {credentials}" + routes: + - exit: http_client0 + when: + - headers: + :path: /items + :method: GET + guarded: + jwt0: + - list:items + - exit: http_client0 + when: + - headers: + :path: /items + :method: POST + guarded: + jwt0: + - create:items + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: GET + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: PUT + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: DELETE + http_client0: + type: http + kind: client + exit: tls_client0 + tls_client0: + vault: client + type: tls + kind: client + options: + trust: + - "${{env.TLS_CLIENT_TRUST}}" + trustcacerts: true + sni: + - "${{env.TLS_CLIENT_SNI}}" + alpn: + - "${{env.TLS_CLIENT_ALPN}}" + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +guards: + jwt0: + type: jwt + options: + issuer: "${{env.JWT_ISSUER}}" + audience: "${{env.JWT_AUDIENCE}}" + keys: + - kty: "${{env.JWT_KTY}}" + "n": "${{env.JWT_N}}" + e: "${{env.JWT_E}}" + alg: "${{env.JWT_ALG}}" + crv: "${{env.JWT_CRV}}" + x: "${{env.JWT_X}}" + "y": "${{env.JWT_Y}}" + use: "${{env.JWT_USE}}" + kid: "${{env.JWT_KID}}" +vaults: + client: + type: filesystem + options: + trust: + store: "${{env.TRUSTSTORE_PATH}}" + type: "${{env.TRUSTSTORE_TYPE}}" + password: "${{env.TRUSTSTORE_PASSWORD}}" + server: + type: filesystem + options: + keys: + store: "${{env.KEYSTORE_PATH}}" + type: "${{env.KEYSTORE_TYPE}}" + password: "${{env.KEYSTORE_PASSWORD}}" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/jwt/openapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/jwt/openapi.yaml new file mode 100644 index 0000000000..3a7d12a913 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/jwt/openapi.yaml @@ -0,0 +1,168 @@ +openapi: 3.1.0 +hello: $.openapi +info: + version: 1.0.0 + title: Zilla CRUD V1 + license: + name: Aklivity Community License +servers: + - url: http://localhost:8080 +paths: + /items: + post: + summary: Create an item + operationId: createItem + tags: + - items + requestBody: + content: + 'application/json': + schema: + $ref: '#/components/schemas/Item' + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + security: + - bearerAuth: + - create:items + get: + summary: List all items + operationId: listItems + tags: + - items + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + maximum: 100 + format: int32 + responses: + '200': + description: A paged array of items + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Items" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + security: + - bearerAuth: + - list:items + /items/{id}: + get: + summary: Get an item + operationId: showItemById + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Item" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + put: + summary: Update an item by key + operationId: updateItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to update + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + delete: + summary: Delete an item by key + operationId: deleteItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to delete + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Item: + type: object + required: + - greeting + properties: + greeting: + type: string + tag: + type: string + Items: + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/Item" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: jwt diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/jwt/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/jwt/zilla.yaml new file mode 100644 index 0000000000..21fb5261cb --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/jwt/zilla.yaml @@ -0,0 +1,81 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 8080 + routes: + - exit: http_server0 + when: + - port: 8080 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + authorization: + jwt0: + credentials: + headers: + authorization: "Bearer {credentials}" + routes: + - exit: http_client0 + when: + - headers: + :path: /items + :method: GET + guarded: + jwt0: + - list:items + - exit: http_client0 + when: + - headers: + :path: /items + :method: POST + guarded: + jwt0: + - create:items + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: GET + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: PUT + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: DELETE + http_client0: + type: http + kind: client + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +guards: + jwt0: + type: jwt + options: + issuer: "${{env.JWT_ISSUER}}" + audience: "${{env.JWT_AUDIENCE}}" + keys: + - kty: "${{env.JWT_KTY}}" + "n": "${{env.JWT_N}}" + e: "${{env.JWT_E}}" + alg: "${{env.JWT_ALG}}" + crv: "${{env.JWT_CRV}}" + x: "${{env.JWT_X}}" + "y": "${{env.JWT_Y}}" + use: "${{env.JWT_USE}}" + kid: "${{env.JWT_KID}}" diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/plain/openapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/plain/openapi.yaml new file mode 100644 index 0000000000..712761e416 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/plain/openapi.yaml @@ -0,0 +1,157 @@ +openapi: 3.1.0 +hello: $.openapi +info: + version: 1.0.0 + title: Zilla CRUD V1 + license: + name: Aklivity Community License +servers: + - url: http://localhost:8080 +paths: + /items: + post: + summary: Create an item + operationId: createItem + tags: + - items + requestBody: + content: + 'application/json': + schema: + $ref: '#/components/schemas/Item' + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + get: + summary: List all items + operationId: listItems + tags: + - items + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + maximum: 100 + format: int32 + responses: + '200': + description: A paged array of items + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Items" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /items/{id}: + get: + summary: Get an item + operationId: showItemById + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Item" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + put: + summary: Update an item by key + operationId: updateItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to update + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + delete: + summary: Delete an item by key + operationId: deleteItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to delete + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Item: + type: object + required: + - greeting + properties: + greeting: + type: string + tag: + type: string + Items: + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/Item" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/plain/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/plain/zilla.yaml new file mode 100644 index 0000000000..057c2a4c62 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/plain/zilla.yaml @@ -0,0 +1,54 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 8080 + routes: + - exit: http_server0 + when: + - port: 8080 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + routes: + - exit: http_client0 + when: + - headers: + :path: /items + :method: GET + - exit: http_client0 + when: + - headers: + :path: /items + :method: POST + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: GET + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: PUT + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: DELETE + http_client0: + type: http + kind: client + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/tls/openapi.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/tls/openapi.yaml new file mode 100644 index 0000000000..53b1c6d2b9 --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/tls/openapi.yaml @@ -0,0 +1,157 @@ +openapi: 3.1.0 +hello: $.openapi +info: + version: 1.0.0 + title: Zilla CRUD V1 + license: + name: Aklivity Community License +servers: + - url: https://localhost:9090 +paths: + /items: + post: + summary: Create an item + operationId: createItem + tags: + - items + requestBody: + content: + 'application/json': + schema: + $ref: '#/components/schemas/Item' + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + get: + summary: List all items + operationId: listItems + tags: + - items + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + maximum: 100 + format: int32 + responses: + '200': + description: A paged array of items + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Items" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /items/{id}: + get: + summary: Get an item + operationId: showItemById + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Item" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + put: + summary: Update an item by key + operationId: updateItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to update + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + delete: + summary: Delete an item by key + operationId: deleteItem + tags: + - items + parameters: + - name: id + in: path + required: true + description: The id of the item to delete + schema: + type: string + responses: + '204': + description: No Content + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Item: + type: object + required: + - greeting + properties: + greeting: + type: string + tag: + type: string + Items: + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/Item" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/tls/zilla.yaml b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/tls/zilla.yaml new file mode 100644 index 0000000000..22e4b1c9df --- /dev/null +++ b/incubator/command-config/src/test/resources/io/aklivity/zilla/runtime/command/config/internal/openapi/http/proxy/tls/zilla.yaml @@ -0,0 +1,94 @@ +name: example +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 9090 + routes: + - exit: tls_server0 + when: + - port: 9090 + tls_server0: + vault: server + type: tls + kind: server + options: + keys: + - "${{env.TLS_SERVER_KEY}}" + sni: + - "${{env.TLS_SERVER_SNI}}" + alpn: + - "${{env.TLS_SERVER_ALPN}}" + exit: http_server0 + http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + routes: + - exit: http_client0 + when: + - headers: + :path: /items + :method: GET + - exit: http_client0 + when: + - headers: + :path: /items + :method: POST + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: GET + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: PUT + - exit: http_client0 + when: + - headers: + :path: /items/* + :method: DELETE + http_client0: + type: http + kind: client + exit: tls_client0 + tls_client0: + vault: client + type: tls + kind: client + options: + trust: + - "${{env.TLS_CLIENT_TRUST}}" + trustcacerts: true + sni: + - "${{env.TLS_CLIENT_SNI}}" + alpn: + - "${{env.TLS_CLIENT_ALPN}}" + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: "${{env.TCP_CLIENT_HOST}}" + port: ${{env.TCP_CLIENT_PORT}} +vaults: + client: + type: filesystem + options: + trust: + store: "${{env.TRUSTSTORE_PATH}}" + type: "${{env.TRUSTSTORE_TYPE}}" + password: "${{env.TRUSTSTORE_PASSWORD}}" + server: + type: filesystem + options: + keys: + store: "${{env.KEYSTORE_PATH}}" + type: "${{env.KEYSTORE_TYPE}}" + password: "${{env.KEYSTORE_PASSWORD}}" diff --git a/incubator/command-dump/pom.xml b/incubator/command-dump/pom.xml index f33a68f99e..ef5f6816d3 100644 --- a/incubator/command-dump/pom.xml +++ b/incubator/command-dump/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla incubator - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/command-log/NOTICE b/incubator/command-log/NOTICE index 825692ba5b..e632206ebd 100644 --- a/incubator/command-log/NOTICE +++ b/incubator/command-log/NOTICE @@ -15,9 +15,14 @@ This project includes: agrona under The Apache License, Version 2.0 Apache Commons CLI under Apache License, Version 2.0 ICU4J under Unicode/ICU License + Jackson-annotations under The Apache Software License, Version 2.0 + Jackson-core under The Apache Software License, Version 2.0 + jackson-databind under The Apache Software License, Version 2.0 + Jackson-dataformat-YAML under The Apache Software License, Version 2.0 Jakarta JSON Processing API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception JSON-B API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception org.leadpony.justify under The Apache Software License, Version 2.0 + SnakeYAML under Apache License, Version 2.0 zilla::runtime::engine under The Apache Software License, Version 2.0 diff --git a/incubator/command-log/pom.xml b/incubator/command-log/pom.xml index a36a20ea38..1858cdde56 100644 --- a/incubator/command-log/pom.xml +++ b/incubator/command-log/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla incubator - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java b/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java index f857dd303d..9a5822a5b7 100644 --- a/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java +++ b/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java @@ -45,8 +45,6 @@ import io.aklivity.zilla.runtime.command.log.internal.types.KafkaPartitionFW; import io.aklivity.zilla.runtime.command.log.internal.types.KafkaSkipFW; import io.aklivity.zilla.runtime.command.log.internal.types.KafkaValueMatchFW; -import io.aklivity.zilla.runtime.command.log.internal.types.MqttEndReasonCode; -import io.aklivity.zilla.runtime.command.log.internal.types.MqttMessageFW; import io.aklivity.zilla.runtime.command.log.internal.types.MqttPayloadFormat; import io.aklivity.zilla.runtime.command.log.internal.types.MqttTopicFilterFW; import io.aklivity.zilla.runtime.command.log.internal.types.MqttUserPropertyFW; @@ -80,6 +78,9 @@ import io.aklivity.zilla.runtime.command.log.internal.types.stream.HttpFlushExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaBootstrapBeginExFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaConsumerAssignmentFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaConsumerBeginExFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaConsumerDataExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaDataExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaDescribeBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaDescribeDataExFW; @@ -87,6 +88,8 @@ import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaFetchDataExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaFetchFlushExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaFlushExFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaGroupBeginExFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaGroupFlushExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaMergedBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaMergedDataExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaMergedFlushExFW; @@ -95,9 +98,9 @@ import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaProduceBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaProduceDataExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.KafkaTopicPartitionFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttDataExFW; -import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttEndExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttFlushExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttPublishBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttPublishDataExFW; @@ -143,7 +146,6 @@ public final class LoggableStream implements AutoCloseable private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); private final MqttFlushExFW mqttFlushExRO = new MqttFlushExFW(); - private final MqttEndExFW mqttEndExRO = new MqttEndExFW(); private final AmqpBeginExFW amqpBeginExRO = new AmqpBeginExFW(); private final AmqpDataExFW amqpDataExRO = new AmqpDataExFW(); @@ -267,7 +269,6 @@ public final class LoggableStream implements AutoCloseable beginHandlers.put(labels.lookupLabelId("mqtt"), this::onMqttBeginEx); dataHandlers.put(labels.lookupLabelId("mqtt"), this::onMqttDataEx); flushHandlers.put(labels.lookupLabelId("mqtt"), this::onMqttFlushEx); - endHandlers.put(labels.lookupLabelId("mqtt"), this::onMqttEndEx); } if (hasExtensionType.test("amqp")) @@ -890,6 +891,12 @@ private void onKafkaBeginEx( case KafkaBeginExFW.KIND_DESCRIBE: onKafkaDescribeBeginEx(offset, timestamp, kafkaBeginEx.describe()); break; + case KafkaBeginExFW.KIND_GROUP: + onKafkaGroupBeginEx(offset, timestamp, kafkaBeginEx.group()); + break; + case KafkaBeginExFW.KIND_CONSUMER: + onKafkaConsumerBeginEx(offset, timestamp, kafkaBeginEx.consumer()); + break; case KafkaBeginExFW.KIND_FETCH: onKafkaFetchBeginEx(offset, timestamp, kafkaBeginEx.fetch()); break; @@ -946,6 +953,35 @@ private void onKafkaDescribeBeginEx( configs.forEach(c -> out.printf(verboseFormat, index, offset, timestamp, c.asString())); } + private void onKafkaGroupBeginEx( + int offset, + long timestamp, + KafkaGroupBeginExFW group) + { + String16FW groupId = group.groupId(); + String16FW protocol = group.protocol(); + int timeout = group.timeout(); + + out.printf(verboseFormat, index, offset, timestamp, format("[group] %s %s %d", + groupId.asString(), protocol.asString(), timeout)); + } + + private void onKafkaConsumerBeginEx( + int offset, + long timestamp, + KafkaConsumerBeginExFW consumer) + { + String16FW groupId = consumer.groupId(); + String16FW consumerId = consumer.consumerId(); + String16FW topic = consumer.topic(); + int timeout = consumer.timeout(); + Array32FW partitions = consumer.partitionIds(); + + out.printf(verboseFormat, index, offset, timestamp, format("[consumer] %s %s %s %d", + groupId.asString(), consumerId.asString(), topic.asString(), timeout)); + partitions.forEach(p -> out.printf(verboseFormat, index, offset, timestamp, format("%d", p.partitionId()))); + } + private void onKafkaFetchBeginEx( int offset, long timestamp, @@ -1065,6 +1101,9 @@ private void onKafkaDataEx( case KafkaDataExFW.KIND_FETCH: onKafkaFetchDataEx(offset, timestamp, kafkaDataEx.fetch()); break; + case KafkaDataExFW.KIND_CONSUMER: + onKafkaConsumerDataEx(offset, timestamp, kafkaDataEx.consumer()); + break; case KafkaDataExFW.KIND_MERGED: onKafkaMergedDataEx(offset, timestamp, kafkaDataEx.merged()); break; @@ -1109,6 +1148,25 @@ private void onKafkaFetchDataEx( format("%s: %s", asString(h.name()), asString(h.value())))); } + private void onKafkaConsumerDataEx( + int offset, + long timestamp, + KafkaConsumerDataExFW consumer) + { + Array32FW partitions = consumer.partitions(); + Array32FW assignments = consumer.assignments(); + + out.printf(verboseFormat, index, offset, timestamp, "[consumer]"); + partitions.forEach(p -> out.printf(verboseFormat, index, offset, timestamp, + format("%d", p.partitionId()))); + assignments.forEach(a -> + { + out.printf(verboseFormat, index, offset, timestamp, a.consumerId().asString()); + a.partitions().forEach(p -> + out.printf(verboseFormat, index, offset, timestamp, format("%d", p.partitionId()))); + }); + } + private void onKafkaMergedDataEx( int offset, long timestamp, @@ -1168,6 +1226,9 @@ private void onKafkaFlushEx( case KafkaFlushExFW.KIND_MERGED: onKafkaMergedFlushEx(offset, timestamp, kafkaFlushEx.merged()); break; + case KafkaFlushExFW.KIND_GROUP: + onKafkaGroupFlushEx(offset, timestamp, kafkaFlushEx.group()); + break; case KafkaFlushExFW.KIND_FETCH: onKafkaFetchFlushEx(offset, timestamp, kafkaFlushEx.fetch()); break; @@ -1179,8 +1240,8 @@ private void onKafkaMergedFlushEx( long timestamp, KafkaMergedFlushExFW merged) { - final ArrayFW progress = merged.progress(); - final Array32FW filters = merged.filters(); + final ArrayFW progress = merged.fetch().progress(); + final Array32FW filters = merged.fetch().filters(); out.printf(verboseFormat, index, offset, timestamp, "[merged]"); progress.forEach(p -> out.printf(verboseFormat, index, offset, timestamp, @@ -1192,6 +1253,18 @@ private void onKafkaMergedFlushEx( filters.forEach(f -> f.conditions().forEach(c -> out.printf(verboseFormat, index, offset, timestamp, asString(c)))); } + private void onKafkaGroupFlushEx( + int offset, + long timestamp, + KafkaGroupFlushExFW group) + { + String16FW leader = group.leaderId(); + String16FW member = group.memberId(); + + out.printf(verboseFormat, index, offset, timestamp, format("[group] %s %s (%d)", leader.asString(), + member.asString(), group.members().fieldCount())); + } + private void onKafkaFetchFlushEx( int offset, long timestamp, @@ -1278,34 +1351,9 @@ private void onMqttSessionBeginEx( { final String clientId = session.clientId().asString(); final int expiry = session.expiry(); - final MqttMessageFW will = session.will(); out.printf(verboseFormat, index, offset, timestamp, format("[session] %s %d", clientId, expiry)); - if (will != null) - { - final String willTopic = will.topic().asString(); - final int delay = will.delay(); - final int flags = will.flags(); - final int expiryInterval = will.expiryInterval(); - final String contentType = will.contentType().asString(); - final MqttPayloadFormat format = will.format().get(); - final String responseTopic = will.responseTopic().asString(); - final String correlation = asString(will.correlation().bytes()); - final Array32FW userProperties = will.properties(); - final String payload = asString(will.payload().bytes()); - out.printf(verboseFormat, index, offset, timestamp, format("will topic: %s", willTopic)); - out.printf(verboseFormat, index, offset, timestamp, format("will delay: %d", delay)); - out.printf(verboseFormat, index, offset, timestamp, format("will flags: %d", flags)); - out.printf(verboseFormat, index, offset, timestamp, format("will expiry: %d", expiryInterval)); - out.printf(verboseFormat, index, offset, timestamp, format("will content type: %s", contentType)); - out.printf(verboseFormat, index, offset, timestamp, format("will format: %s", format.name())); - out.printf(verboseFormat, index, offset, timestamp, format("will response topic: %s", responseTopic)); - out.printf(verboseFormat, index, offset, timestamp, format("will correlation: %s", correlation)); - out.printf(verboseFormat, index, offset, timestamp, format("will payload: %s", payload)); - userProperties.forEach(u -> out.printf(verboseFormat, index, offset, timestamp, - format("will user property: %s %s ", u.key(), u.value()))); - } } private void onMqttDataEx( @@ -1334,7 +1382,6 @@ private void onMqttPublishDataEx( MqttPublishDataExFW publish) { final int deferred = publish.deferred(); - final String topic = publish.topic().asString(); final int flags = publish.flags(); final int expiryInterval = publish.expiryInterval(); final String contentType = publish.contentType().asString(); @@ -1344,8 +1391,8 @@ private void onMqttPublishDataEx( final Array32FW properties = publish.properties(); out.printf(verboseFormat, index, offset, timestamp, - format("[publish] (%d) %s %d %d %s %s %s %s", - deferred, topic, flags, expiryInterval, contentType, format.name(), responseTopic, correlation)); + format("[publish] (%d) %d %d %s %s %s %s", + deferred, flags, expiryInterval, contentType, format.name(), responseTopic, correlation)); properties.forEach(u -> out.printf(verboseFormat, index, offset, timestamp, format("%s %s ", u.key(), u.value()))); } @@ -1389,18 +1436,6 @@ private void onMqttFlushEx( format("%s %d %d", f.pattern(), f.subscriptionId(), f.flags()))); } - private void onMqttEndEx( - final EndFW end) - { - final int offset = end.offset() - HEADER_LENGTH; - final long timestamp = end.timestamp(); - final OctetsFW extension = end.extension(); - - final MqttEndExFW mqttEndEx = mqttEndExRO.wrap(extension.buffer(), extension.offset(), extension.limit()); - final MqttEndReasonCode reasonCode = mqttEndEx.reasonCode().get(); - out.printf(verboseFormat, index, offset, timestamp, format("%s", reasonCode.name())); - } - private void onAmqpBeginEx( final BeginFW begin) { diff --git a/incubator/command-tune/pom.xml b/incubator/command-tune/pom.xml index ca3084fedf..bef4dcbf15 100644 --- a/incubator/command-tune/pom.xml +++ b/incubator/command-tune/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla incubator - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/exporter-otlp.spec/pom.xml b/incubator/exporter-otlp.spec/pom.xml index c1b55b2968..e3cf97248c 100644 --- a/incubator/exporter-otlp.spec/pom.xml +++ b/incubator/exporter-otlp.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla incubator - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/exporter-otlp/pom.xml b/incubator/exporter-otlp/pom.xml index efcf975624..828ae7928a 100644 --- a/incubator/exporter-otlp/pom.xml +++ b/incubator/exporter-otlp/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla incubator - 0.9.51 + 0.9.52 ../pom.xml diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpEndpointConfig.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpEndpointConfig.java similarity index 83% rename from incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpEndpointConfig.java rename to incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpEndpointConfig.java index f6844e3006..78b507b7d1 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpEndpointConfig.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpEndpointConfig.java @@ -12,13 +12,11 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.exporter.otlp.internal.config; +package io.aklivity.zilla.runtime.exporter.otlp.config; import java.net.URI; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public class OtlpEndpointConfig extends OptionsConfig +public class OtlpEndpointConfig { public String protocol; public URI location; diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOptionsConfig.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpOptionsConfig.java similarity index 94% rename from incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOptionsConfig.java rename to incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpOptionsConfig.java index 119a961a40..d5bb3f24c5 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOptionsConfig.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpOptionsConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.exporter.otlp.internal.config; +package io.aklivity.zilla.runtime.exporter.otlp.config; import java.util.Set; diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOverridesConfig.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpOverridesConfig.java similarity index 80% rename from incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOverridesConfig.java rename to incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpOverridesConfig.java index 95c8f81384..7fa6fc009d 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOverridesConfig.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/config/OtlpOverridesConfig.java @@ -12,13 +12,11 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.exporter.otlp.internal.config; +package io.aklivity.zilla.runtime.exporter.otlp.config; import java.net.URI; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public class OtlpOverridesConfig extends OptionsConfig +public class OtlpOverridesConfig { public URI metrics; diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/OltpExporterHandler.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/OltpExporterHandler.java index 194e71208d..1fff2ab6bd 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/OltpExporterHandler.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/OltpExporterHandler.java @@ -14,7 +14,7 @@ */ package io.aklivity.zilla.runtime.exporter.otlp.internal; -import static io.aklivity.zilla.runtime.exporter.otlp.internal.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; +import static io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; import java.net.HttpURLConnection; import java.net.URI; @@ -34,8 +34,8 @@ import io.aklivity.zilla.runtime.engine.exporter.ExporterHandler; import io.aklivity.zilla.runtime.engine.metrics.Collector; import io.aklivity.zilla.runtime.engine.metrics.reader.MetricsReader; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig; import io.aklivity.zilla.runtime.exporter.otlp.internal.config.OtlpExporterConfig; -import io.aklivity.zilla.runtime.exporter.otlp.internal.config.OtlpOptionsConfig; import io.aklivity.zilla.runtime.exporter.otlp.internal.serializer.OtlpMetricsSerializer; public class OltpExporterHandler implements ExporterHandler diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpEndpointAdapter.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpEndpointAdapter.java index 25bf80fcea..1ba739dffc 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpEndpointAdapter.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpEndpointAdapter.java @@ -21,6 +21,9 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpEndpointConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOverridesConfig; + public class OtlpEndpointAdapter implements JsonbAdapter { private static final String PROTOCOL_NAME = "protocol"; diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfig.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfig.java index a7cac677c2..b6b15c2cf5 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfig.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfig.java @@ -14,13 +14,14 @@ */ package io.aklivity.zilla.runtime.exporter.otlp.internal.config; -import static io.aklivity.zilla.runtime.exporter.otlp.internal.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; +import static io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; import java.net.URI; import java.time.Duration; import java.util.Set; import io.aklivity.zilla.runtime.engine.config.ExporterConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig; public class OtlpExporterConfig { diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOptionsConfigAdapter.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOptionsConfigAdapter.java index ebf61f6737..d49b32708d 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOptionsConfigAdapter.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOptionsConfigAdapter.java @@ -25,6 +25,8 @@ import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpEndpointConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig; import io.aklivity.zilla.runtime.exporter.otlp.internal.OtlpExporter; public class OtlpOptionsConfigAdapter implements OptionsConfigAdapterSpi, JsonbAdapter diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOverridesAdapter.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOverridesAdapter.java index 708687ac2e..5957e244b8 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOverridesAdapter.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpOverridesAdapter.java @@ -21,6 +21,8 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOverridesConfig; + public class OtlpOverridesAdapter implements JsonbAdapter { private static final String METRICS_NAME = "metrics"; diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpSignalsAdapter.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpSignalsAdapter.java index 2e799f6eff..7e8f90a052 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpSignalsAdapter.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpSignalsAdapter.java @@ -14,7 +14,7 @@ */ package io.aklivity.zilla.runtime.exporter.otlp.internal.config; -import static io.aklivity.zilla.runtime.exporter.otlp.internal.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; +import static io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; import java.util.Set; import java.util.TreeSet; @@ -24,6 +24,8 @@ import jakarta.json.JsonArrayBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig; + public class OtlpSignalsAdapter implements JsonbAdapter, JsonArray> { private static final String METRICS_NAME = "metrics"; diff --git a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java index 301005aa6d..b5499c11b9 100644 --- a/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java +++ b/incubator/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java @@ -141,8 +141,14 @@ private JsonArrayBuilder attributes( MetricRecord record) { return attributesToJson(List.of( - new AttributeConfig("namespace", record.namespace()), - new AttributeConfig("binding", record.binding()) + AttributeConfig.builder() + .name("namespace") + .value(record.namespace()) + .build(), + AttributeConfig.builder() + .name("binding") + .value(record.binding()) + .build() )); } diff --git a/incubator/exporter-otlp/src/main/moditect/module-info.java b/incubator/exporter-otlp/src/main/moditect/module-info.java index 535428885e..5f3622e7c7 100644 --- a/incubator/exporter-otlp/src/main/moditect/module-info.java +++ b/incubator/exporter-otlp/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ requires java.net.http; requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.exporter.otlp.config; + provides io.aklivity.zilla.runtime.engine.exporter.ExporterFactorySpi with io.aklivity.zilla.runtime.exporter.otlp.internal.OtlpExporterFactorySpi; diff --git a/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OltpOptionsConfigAdapterTest.java b/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OltpOptionsConfigAdapterTest.java index 93730297cd..21a94a613f 100644 --- a/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OltpOptionsConfigAdapterTest.java +++ b/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OltpOptionsConfigAdapterTest.java @@ -14,7 +14,7 @@ */ package io.aklivity.zilla.runtime.exporter.otlp.internal.config; -import static io.aklivity.zilla.runtime.exporter.otlp.internal.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; +import static io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; @@ -31,6 +31,10 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpEndpointConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOverridesConfig; + public class OltpOptionsConfigAdapterTest { private Jsonb jsonb; diff --git a/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfigTest.java b/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfigTest.java index 1c7404b218..3dc2808cd8 100644 --- a/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfigTest.java +++ b/incubator/exporter-otlp/src/test/java/io/aklivity/zilla/runtime/exporter/otlp/internal/config/OtlpExporterConfigTest.java @@ -14,7 +14,7 @@ */ package io.aklivity.zilla.runtime.exporter.otlp.internal.config; -import static io.aklivity.zilla.runtime.exporter.otlp.internal.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; +import static io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig.OtlpSignalsConfig.METRICS; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; @@ -24,6 +24,9 @@ import org.junit.Test; import io.aklivity.zilla.runtime.engine.config.ExporterConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpEndpointConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOptionsConfig; +import io.aklivity.zilla.runtime.exporter.otlp.config.OtlpOverridesConfig; public class OtlpExporterConfigTest { @@ -34,7 +37,11 @@ public void shouldCreateDefaultMetricsUrl() OtlpOverridesConfig overrides = new OtlpOverridesConfig(null); OtlpEndpointConfig endpoint = new OtlpEndpointConfig("http", URI.create("http://example.com"), overrides); OtlpOptionsConfig options = new OtlpOptionsConfig(30L, Set.of(METRICS), endpoint); - ExporterConfig exporter = new ExporterConfig("oltp0", "oltp", options); + ExporterConfig exporter = ExporterConfig.builder() + .name("oltp0") + .type("oltp") + .options(options) + .build(); OtlpExporterConfig oltpExporter = new OtlpExporterConfig(exporter); // WHEN @@ -51,7 +58,11 @@ public void shouldOverrideAbsoluteMetricsUrl() OtlpOverridesConfig overrides = new OtlpOverridesConfig(URI.create("http://overridden.com/metrics")); OtlpEndpointConfig endpoint = new OtlpEndpointConfig("http", URI.create("http://example.com"), overrides); OtlpOptionsConfig options = new OtlpOptionsConfig(30L, Set.of(METRICS), endpoint); - ExporterConfig exporter = new ExporterConfig("oltp0", "oltp", options); + ExporterConfig exporter = ExporterConfig.builder() + .name("oltp0") + .type("oltp") + .options(options) + .build(); OtlpExporterConfig oltpExporter = new OtlpExporterConfig(exporter); // WHEN @@ -68,7 +79,11 @@ public void shouldOverrideRelativeMetricsUrl() OtlpOverridesConfig overrides = new OtlpOverridesConfig(URI.create("/v42/metrix")); OtlpEndpointConfig endpoint = new OtlpEndpointConfig("http", URI.create("http://example.com"), overrides); OtlpOptionsConfig options = new OtlpOptionsConfig(30L, Set.of(METRICS), endpoint); - ExporterConfig exporter = new ExporterConfig("oltp0", "oltp", options); + ExporterConfig exporter = ExporterConfig.builder() + .name("oltp0") + .type("oltp") + .options(options) + .build(); OtlpExporterConfig oltpExporter = new OtlpExporterConfig(exporter); // WHEN diff --git a/incubator/pom.xml b/incubator/pom.xml index fed8f634b2..d9e48c1a84 100644 --- a/incubator/pom.xml +++ b/incubator/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla zilla - 0.9.51 + 0.9.52 ../pom.xml @@ -18,17 +18,14 @@ binding-amqp.spec - binding-mqtt.spec - binding-mqtt-kafka.spec exporter-otlp.spec binding-amqp - binding-mqtt - binding-mqtt-kafka command-log command-dump command-tune + command-config exporter-otlp @@ -42,27 +39,22 @@ ${project.groupId} - binding-mqtt - ${project.version} - - - ${project.groupId} - binding-mqtt-kafka + command-log ${project.version} ${project.groupId} - command-log + command-tune ${project.version} ${project.groupId} - command-tune + command-dump ${project.version} ${project.groupId} - command-dump + command-config ${project.version} diff --git a/manager/NOTICE b/manager/NOTICE index 3ee3390cb0..42f45c5be2 100644 --- a/manager/NOTICE +++ b/manager/NOTICE @@ -22,10 +22,10 @@ This project includes: JSON-B API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception JSON-P Default Provider under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception org.eclipse.yasson under Eclipse Public License v. 2.0 or Eclipse Distribution License v. 1.0 - Plexus :: Component Annotations under The Apache Software License, Version 2.0 + Plexus :: Component Annotations under Apache License, Version 2.0 Plexus Cipher: encryption/decryption Component under Apache Public License 2.0 - Plexus Classworlds under The Apache Software License, Version 2.0 - Plexus Common Utilities under The Apache Software License, Version 2.0 + Plexus Classworlds under Apache License, Version 2.0 + Plexus Common Utilities under Apache License, Version 2.0 Plexus Security Dispatcher Component under Apache Public License 2.0 Sisu-Inject-Plexus : Aggregate OSGi bundle under Eclipse Public License, Version 1.0 diff --git a/manager/pom.xml b/manager/pom.xml index 110c3b3a07..77d4e0d970 100644 --- a/manager/pom.xml +++ b/manager/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla zilla - 0.9.51 + 0.9.52 ../pom.xml @@ -35,12 +35,12 @@ org.apache.ivy ivy - 2.5.1 + 2.5.2 org.sonatype.plexus plexus-sec-dispatcher - 1.3 + 1.4 org.sonatype.sisu diff --git a/manager/src/main/java/io/aklivity/zilla/manager/internal/commands/install/ZpmInstall.java b/manager/src/main/java/io/aklivity/zilla/manager/internal/commands/install/ZpmInstall.java index 8122cc14dc..85343e48e0 100644 --- a/manager/src/main/java/io/aklivity/zilla/manager/internal/commands/install/ZpmInstall.java +++ b/manager/src/main/java/io/aklivity/zilla/manager/internal/commands/install/ZpmInstall.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.manager.internal.commands.install; import static io.aklivity.zilla.manager.internal.settings.ZpmSecrets.decryptSecret; +import static java.io.OutputStream.nullOutputStream; import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.Files.createDirectories; import static java.nio.file.Files.getLastModifiedTime; @@ -34,6 +35,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.PrintStream; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; @@ -178,13 +180,13 @@ public void invoke() ZpmModule delegate = new ZpmModule(); Collection modules = discoverModules(artifacts); migrateUnnamed(modules, delegate); - generateSystemOnlyAutomatic(modules); + generateSystemOnlyAutomatic(logger, modules); delegateAutomatic(modules, delegate); copyNonDelegating(modules); if (!delegate.paths.isEmpty()) { - generateDelegate(delegate); + generateDelegate(logger, delegate); generateDelegating(modules); } @@ -396,6 +398,7 @@ private void delegateModule( } private void generateSystemOnlyAutomatic( + MessageLogger logger, Collection modules) throws IOException { Map promotions = new IdentityHashMap<>(); @@ -415,21 +418,24 @@ private void generateSystemOnlyAutomatic( Path artifactPath = module.paths.iterator().next(); ToolProvider jdeps = ToolProvider.findFirst("jdeps").get(); + PrintStream nullOutput = new PrintStream(nullOutputStream()); jdeps.run( - System.out, - System.err, + nullOutput, + nullOutput, "--generate-open-module", generatedModulesDir.toString(), artifactPath.toString()); Path generatedModuleInfo = generatedModuleDir.resolve(MODULE_INFO_JAVA_FILENAME); if (Files.exists(generatedModuleInfo)) { + logger.info(String.format("Generated module info for system-only automatic module: %s", module.name)); + expandJar(generatedModuleDir, artifactPath); ToolProvider javac = ToolProvider.findFirst("javac").get(); javac.run( - System.out, - System.err, + nullOutput, + nullOutput, "-d", generatedModuleDir.toString(), generatedModuleInfo.toString()); @@ -478,6 +484,7 @@ private void copyNonDelegating( } private void generateDelegate( + MessageLogger logger, ZpmModule delegate) throws IOException { Path generatedModulesDir = generatedDir.resolve("modules"); @@ -562,7 +569,13 @@ else if (entryNames.add(entryName)) jdepsArgs.toArray(String[]::new)); Path generatedModuleInfo = generatedDelegateDir.resolve(MODULE_INFO_JAVA_FILENAME); - assert Files.exists(generatedModuleInfo); + + if (!Files.exists(generatedModuleInfo)) + { + throw new IOException("Failed to generate module info for delegate module"); + } + + logger.info(String.format("Generated module info for delegate module\n")); String moduleInfoContents = Files.readString(generatedModuleInfo); Pattern pattern = Pattern.compile("(?:provides\\s+)([^\\s]+)(?:\\s+with)"); @@ -718,8 +731,12 @@ private void expandJar( { for (JarEntry entry : list(sourceJar.entries())) { - Path entryPath = targetDir.resolve(entry.getName()); - if (entry.isDirectory()) + Path entryPath = targetDir.resolve(entry.getName()).normalize(); + if (!entryPath.startsWith(targetDir)) + { + throw new IOException("Bad zip entry"); + } + else if (entry.isDirectory()) { createDirectories(entryPath); } diff --git a/pom.xml b/pom.xml index 8747432e2b..1180678685 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 io.aklivity.zilla zilla - 0.9.51 + 0.9.52 pom zilla https://github.com/aklivity/zilla @@ -44,10 +44,10 @@ UTF-8 io/aklivity/zilla/conf/checkstyle/configuration.xml io/aklivity/zilla/conf/checkstyle/suppressions.xml - 4.11.1 + 4.13.0 1.6.0 5.8.2 - 4.0.20 + 4.0.21 2.6.0 5.3.1 3.1.0 @@ -65,6 +65,13 @@ + + org.apache.maven + maven + 3.9.4 + pom + import + jakarta.json jakarta.json-api @@ -93,7 +100,7 @@ junit junit - 4.13.1 + 4.13.2 org.hamcrest @@ -123,7 +130,7 @@ com.squareup javapoet - 1.9.0 + 1.13.0 org.junit.jupiter @@ -145,26 +152,6 @@ mockito-core ${mockito.version} - - org.apache.maven - maven-core - 3.6.0 - - - org.apache.maven - maven-artifact - 3.5.0 - - - org.apache.maven - maven-compat - 3.6.0 - - - org.apache.maven.plugin-tools - maven-plugin-annotations - 3.5 - org.apache.maven.plugin-testing maven-plugin-testing-harness @@ -249,6 +236,7 @@ compile + true @@ -278,7 +266,7 @@ com.mycila license-maven-plugin - 4.1 + 4.2
COPYRIGHT
@@ -355,12 +343,12 @@ org.apache.maven.plugins maven-plugin-plugin - 3.5 + 3.9.0 org.apache.maven.plugins maven-compiler-plugin - 3.8.0 + 3.11.0 org.apache.maven.plugins @@ -370,12 +358,12 @@ org.codehaus.mojo exec-maven-plugin - 1.6.0 + 3.1.0 org.moditect moditect-maven-plugin - 1.0.0.RC1 + 1.0.0.Final src/main/moditect/module-info.java @@ -401,7 +389,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.3.0 org.apache.maven.plugins @@ -495,7 +483,7 @@ junit junit - 4.13.1 + 4.13.2 @@ -689,7 +677,7 @@ org.apache.maven.plugins maven-source-plugin - 3.0.1 + 3.3.0 diff --git a/runtime/binding-echo/pom.xml b/runtime/binding-echo/pom.xml index dbea8873de..14f45bf7f5 100644 --- a/runtime/binding-echo/pom.xml +++ b/runtime/binding-echo/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/streams/ServerIT.java b/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/streams/ServerIT.java index 00d2961f6d..cbfe28fb19 100644 --- a/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/streams/ServerIT.java +++ b/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/streams/ServerIT.java @@ -38,9 +38,7 @@ public class ServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/echo/config") .clean(); diff --git a/runtime/binding-fan/pom.xml b/runtime/binding-fan/pom.xml index 50cbd6dae4..3ac2ef49e6 100644 --- a/runtime/binding-fan/pom.xml +++ b/runtime/binding-fan/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-fan/src/test/java/io/aklivity/zilla/runtime/binding/fan/internal/streams/ServerIT.java b/runtime/binding-fan/src/test/java/io/aklivity/zilla/runtime/binding/fan/internal/streams/ServerIT.java index b851a936b0..b327a0d7d1 100644 --- a/runtime/binding-fan/src/test/java/io/aklivity/zilla/runtime/binding/fan/internal/streams/ServerIT.java +++ b/runtime/binding-fan/src/test/java/io/aklivity/zilla/runtime/binding/fan/internal/streams/ServerIT.java @@ -39,9 +39,7 @@ public class ServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/fan/config") .external("app0") .clean(); diff --git a/runtime/binding-filesystem/pom.xml b/runtime/binding-filesystem/pom.xml index b864af080d..ce7d5bcae5 100644 --- a/runtime/binding-filesystem/pom.xml +++ b/runtime/binding-filesystem/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/config/FileSystemOptionsConfig.java b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/config/FileSystemOptionsConfig.java new file mode 100644 index 0000000000..bbd1d782cd --- /dev/null +++ b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/config/FileSystemOptionsConfig.java @@ -0,0 +1,49 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.filesystem.config; + +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; + +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class FileSystemOptionsConfig extends OptionsConfig +{ + public final URI location; + public final FileSystemSymbolicLinksConfig symlinks; + + private transient FileSystem fileSystem; + + public FileSystemOptionsConfig( + URI location, + FileSystemSymbolicLinksConfig symlinks) + { + this.location = location; + this.symlinks = symlinks; + } + + public FileSystem fileSystem( + URI resolvedRoot) + { + if (fileSystem == null) + { + URI uri = "file".equals(resolvedRoot.getScheme()) ? resolvedRoot.resolve("/") : resolvedRoot; + fileSystem = FileSystems.getFileSystem(uri); + } + + return fileSystem; + } +} diff --git a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemSymbolicLinksConfig.java b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/config/FileSystemSymbolicLinksConfig.java similarity index 90% rename from runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemSymbolicLinksConfig.java rename to runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/config/FileSystemSymbolicLinksConfig.java index 47e236df9c..d346dc56e1 100644 --- a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemSymbolicLinksConfig.java +++ b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/config/FileSystemSymbolicLinksConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.filesystem.internal.config; +package io.aklivity.zilla.runtime.binding.filesystem.config; public enum FileSystemSymbolicLinksConfig { diff --git a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/FileSystemConfiguration.java b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/FileSystemConfiguration.java index 9f38a4e9c8..c9f1e7adc4 100644 --- a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/FileSystemConfiguration.java +++ b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/FileSystemConfiguration.java @@ -30,8 +30,8 @@ public class FileSystemConfiguration extends Configuration static { final ConfigurationDef config = new ConfigurationDef(String.format("zilla.binding.%s", NAME)); - FILE_SYSTEM_SERVER_ROOT = - config.property(URI.class, "server.root", FileSystemConfiguration::createURI, p -> createURI(".")); + FILE_SYSTEM_SERVER_ROOT = config.property(URI.class, "server.root", + FileSystemConfiguration::decodeServerRoot, new File(".").toURI()); FILE_SYSTEM_CONFIG = config; } @@ -47,7 +47,7 @@ public URI serverRoot() return FILE_SYSTEM_SERVER_ROOT.get(this); } - private static URI createURI( + private static URI decodeServerRoot( String location) { return location.indexOf(':') != -1 ? URI.create(location) : new File(location).toURI(); diff --git a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemBindingConfig.java b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemBindingConfig.java index 9d34b0746b..85b701bd17 100644 --- a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemBindingConfig.java +++ b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemBindingConfig.java @@ -14,6 +14,7 @@ */ package io.aklivity.zilla.runtime.binding.filesystem.internal.config; +import io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemOptionsConfig; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; diff --git a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfig.java b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfig.java deleted file mode 100644 index 54444b9568..0000000000 --- a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfig.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.filesystem.internal.config; - -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; - -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public final class FileSystemOptionsConfig extends OptionsConfig -{ - public final URI location; - public final FileSystemSymbolicLinksConfig symlinks; - - private transient FileSystem fileSystem; - - public FileSystemOptionsConfig( - URI location, - FileSystemSymbolicLinksConfig symlinks) - { - this.location = location; - this.symlinks = symlinks; - } - - public FileSystem fileSystem( - URI resolvedRoot) - { - if (fileSystem == null) - { - URI uri = "file".equals(resolvedRoot.getScheme()) ? resolvedRoot.resolve("/") : resolvedRoot; - fileSystem = FileSystems.getFileSystem(uri); - } - - return fileSystem; - } -} diff --git a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapter.java b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapter.java index 7318486e71..4b22e9ca73 100644 --- a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapter.java +++ b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapter.java @@ -14,7 +14,7 @@ */ package io.aklivity.zilla.runtime.binding.filesystem.internal.config; -import static io.aklivity.zilla.runtime.binding.filesystem.internal.config.FileSystemSymbolicLinksConfig.IGNORE; +import static io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemSymbolicLinksConfig.IGNORE; import java.net.URI; @@ -23,6 +23,8 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemOptionsConfig; +import io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemSymbolicLinksConfig; import io.aklivity.zilla.runtime.binding.filesystem.internal.FileSystemBinding; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; diff --git a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerFactory.java b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerFactory.java index 0b1e29a1bc..f19ff2d0c9 100644 --- a/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerFactory.java +++ b/runtime/binding-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerFactory.java @@ -14,7 +14,7 @@ */ package io.aklivity.zilla.runtime.binding.filesystem.internal.stream; -import static io.aklivity.zilla.runtime.binding.filesystem.internal.config.FileSystemSymbolicLinksConfig.IGNORE; +import static io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemSymbolicLinksConfig.IGNORE; import static io.aklivity.zilla.runtime.engine.budget.BudgetDebitor.NO_DEBITOR_INDEX; import static java.nio.file.LinkOption.NOFOLLOW_LINKS; import static java.time.Instant.now; @@ -41,11 +41,11 @@ import org.agrona.collections.Long2ObjectHashMap; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemOptionsConfig; import io.aklivity.zilla.runtime.binding.filesystem.internal.FileSystemBinding; import io.aklivity.zilla.runtime.binding.filesystem.internal.FileSystemConfiguration; import io.aklivity.zilla.runtime.binding.filesystem.internal.FileSystemWatcher; import io.aklivity.zilla.runtime.binding.filesystem.internal.config.FileSystemBindingConfig; -import io.aklivity.zilla.runtime.binding.filesystem.internal.config.FileSystemOptionsConfig; import io.aklivity.zilla.runtime.binding.filesystem.internal.types.FileSystemCapabilities; import io.aklivity.zilla.runtime.binding.filesystem.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.filesystem.internal.types.OctetsFW; diff --git a/runtime/binding-filesystem/src/main/moditect/module-info.java b/runtime/binding-filesystem/src/main/moditect/module-info.java index b58f5e84fe..3e6f268443 100644 --- a/runtime/binding-filesystem/src/main/moditect/module-info.java +++ b/runtime/binding-filesystem/src/main/moditect/module-info.java @@ -16,6 +16,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.filesystem.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.filesystem.internal.FileSystemBindingFactorySpi; diff --git a/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java b/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java index 3923795dee..593263191d 100644 --- a/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java +++ b/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java @@ -28,6 +28,9 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemOptionsConfig; +import io.aklivity.zilla.runtime.binding.filesystem.config.FileSystemSymbolicLinksConfig; + public class FileSystemOptionsConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerIT.java b/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerIT.java index de69ccadb8..f4e4ce46ff 100644 --- a/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerIT.java +++ b/runtime/binding-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/filesystem/internal/stream/FileSystemServerIT.java @@ -44,9 +44,7 @@ public class FileSystemServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/filesystem/config") .external("app0") .clean(); diff --git a/runtime/binding-grpc-kafka/pom.xml b/runtime/binding-grpc-kafka/pom.xml index 60996fea5f..ce78aae894 100644 --- a/runtime/binding-grpc-kafka/pom.xml +++ b/runtime/binding-grpc-kafka/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaConditionConfig.java similarity index 84% rename from runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionConfig.java rename to runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaConditionConfig.java index 59ba0f1ba3..1264c4dca1 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionConfig.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaConditionConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.kafka.config; import java.util.Map; @@ -23,12 +23,12 @@ public final class GrpcKafkaConditionConfig extends ConditionConfig { public final String service; public final String method; - public final Map metadata; + public final Map metadata; public GrpcKafkaConditionConfig( String service, String method, - Map metadata) + Map metadata) { this.service = service; this.method = method; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaCorrelationConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaCorrelationConfig.java similarity index 94% rename from runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaCorrelationConfig.java rename to runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaCorrelationConfig.java index 782d48cc7d..b56afa2e24 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaCorrelationConfig.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaCorrelationConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.kafka.config; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaIdempotencyConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaIdempotencyConfig.java similarity index 92% rename from runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaIdempotencyConfig.java rename to runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaIdempotencyConfig.java index 29f6bbf60d..bacda2fb7b 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaIdempotencyConfig.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaIdempotencyConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.kafka.config; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String8FW; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaMetadataValueConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaMetadataValueConfig.java new file mode 100644 index 0000000000..cc66e83413 --- /dev/null +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaMetadataValueConfig.java @@ -0,0 +1,33 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.grpc.kafka.config; + + +import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; + +public class GrpcKafkaMetadataValueConfig +{ + public final String16FW textValue; + public final String16FW base64Value; + + public GrpcKafkaMetadataValueConfig( + String16FW textValue, + String16FW base64Value) + { + + this.textValue = textValue; + this.base64Value = base64Value; + } +} diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaOptionsConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaOptionsConfig.java similarity index 94% rename from runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaOptionsConfig.java rename to runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaOptionsConfig.java index 7723d4ec35..61ffd699f4 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaOptionsConfig.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaOptionsConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.kafka.config; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaReliabilityConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaReliabilityConfig.java similarity index 93% rename from runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaReliabilityConfig.java rename to runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaReliabilityConfig.java index 3c64395f2c..9cf93d65eb 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaReliabilityConfig.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/config/GrpcKafkaReliabilityConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.kafka.config; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String8FW; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaBindingConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaBindingConfig.java index 07da27d9c7..92680945f9 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaBindingConfig.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaBindingConfig.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Optional; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaOptionsConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.stream.GrpcBeginExFW; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapter.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapter.java index 9dc04e65f5..fa829dc196 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapter.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapter.java @@ -29,13 +29,14 @@ import org.agrona.collections.Object2ObjectHashMap; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaConditionConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaMetadataValueConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.GrpcKafkaBinding; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String8FW; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; - public final class GrpcKafkaConditionConfigAdapter implements ConditionConfigAdapterSpi, JsonbAdapter { private static final Pattern METHOD_PATTERN = Pattern.compile("^(?[^/]+)/(?[^/]+)"); @@ -104,7 +105,7 @@ public ConditionConfig adaptFromJson( ? object.getJsonObject(METADATA_NAME) : null; - final Map newMetadata = new Object2ObjectHashMap<>(); + final Map newMetadata = new Object2ObjectHashMap<>(); if (metadata != null) { @@ -129,7 +130,7 @@ public ConditionConfig adaptFromJson( break; } - GrpcKafkaMetadataValue metadataValue = new GrpcKafkaMetadataValue(new String16FW(textValue), + GrpcKafkaMetadataValueConfig metadataValue = new GrpcKafkaMetadataValueConfig(new String16FW(textValue), new String16FW(base64Value)); newMetadata.put(key, metadataValue); }); diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionMatcher.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionMatcher.java index 51445018e4..63dc15005c 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionMatcher.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaConditionMatcher.java @@ -20,6 +20,8 @@ import org.agrona.DirectBuffer; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaConditionConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaMetadataValueConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String8FW; @@ -31,7 +33,7 @@ public final class GrpcKafkaConditionMatcher private final String16FW service; private final String16FW method; - private final Map metadataMatch; + private final Map metadataMatch; public GrpcKafkaConditionMatcher( GrpcKafkaConditionConfig condition) @@ -50,12 +52,12 @@ public boolean matches( if (metadataMatch != null) { - for (Map.Entry entry : metadataMatch.entrySet()) + for (Map.Entry entry : metadataMatch.entrySet()) { final DirectBuffer name = entry.getKey().value(); final GrpcMetadataFW metadata = metadataHeaders.matchFirst(h -> name.compareTo(h.name().value()) == 0); - final GrpcKafkaMetadataValue value = entry.getValue(); + final GrpcKafkaMetadataValueConfig value = entry.getValue(); final DirectBuffer matcher = metadata != null && metadata.type().get() == BASE64 ? value.base64Value.value() : value.textValue.value(); diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaMetadataValue.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaMetadataValue.java deleted file mode 100644 index aab70ed197..0000000000 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaMetadataValue.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config; - - -import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; - -public class GrpcKafkaMetadataValue -{ - public final String16FW textValue; - public final String16FW base64Value; - - public GrpcKafkaMetadataValue( - String16FW textValue, - String16FW base64Value) - { - - this.textValue = textValue; - this.base64Value = base64Value; - } -} diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapter.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapter.java index c55c76e888..ffdf1991e8 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapter.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapter.java @@ -20,6 +20,10 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaCorrelationConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaIdempotencyConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaOptionsConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaReliabilityConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.GrpcKafkaBinding; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String8FW; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaRouteConfig.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaRouteConfig.java index 4f3b96f7da..a04656541d 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaRouteConfig.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaRouteConfig.java @@ -24,15 +24,16 @@ import java.util.regex.MatchResult; import java.util.stream.Collectors; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaConditionConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaOptionsConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.stream.GrpcMetadataFW; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; import io.aklivity.zilla.runtime.engine.util.function.LongObjectBiFunction; -public final class GrpcKafkaRouteConfig extends OptionsConfig +public final class GrpcKafkaRouteConfig { public final long id; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithProduceResult.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithProduceResult.java index d6a1b03032..a5ab3bbc68 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithProduceResult.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithProduceResult.java @@ -20,6 +20,7 @@ import org.agrona.DirectBuffer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaCorrelationConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.KafkaAckMode; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.KafkaAckModeFW; diff --git a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithResolver.java b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithResolver.java index 22d39de0e1..dd84c6acf1 100644 --- a/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithResolver.java +++ b/runtime/binding-grpc-kafka/src/main/java/io/aklivity/zilla/runtime/binding/grpc/kafka/internal/config/GrpcKafkaWithResolver.java @@ -25,6 +25,7 @@ import org.agrona.DirectBuffer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaOptionsConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.stream.GrpcKafkaIdHelper; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.KafkaAckMode; diff --git a/runtime/binding-grpc-kafka/src/main/moditect/module-info.java b/runtime/binding-grpc-kafka/src/main/moditect/module-info.java index 8a6050d029..004272de18 100644 --- a/runtime/binding-grpc-kafka/src/main/moditect/module-info.java +++ b/runtime/binding-grpc-kafka/src/main/moditect/module-info.java @@ -16,6 +16,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.grpc.kafka.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.grpc.kafka.internal.GrpcKafkaBindingFactorySpi; diff --git a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapterTest.java b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapterTest.java index d65ed3289f..dcf0960e2e 100644 --- a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapterTest.java +++ b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaConditionConfigAdapterTest.java @@ -30,9 +30,9 @@ import org.junit.Before; import org.junit.Test; -import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaConditionConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaConditionConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaMetadataValueConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaConditionConfigAdapter; -import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaMetadataValue; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String8FW; @@ -72,7 +72,7 @@ public void shouldReadCondition() public void shouldWriteCondition() { GrpcKafkaConditionConfig condition = new GrpcKafkaConditionConfig("test", "*", - singletonMap(new String8FW("custom"), new GrpcKafkaMetadataValue(new String16FW("test"), + singletonMap(new String8FW("custom"), new GrpcKafkaMetadataValueConfig(new String16FW("test"), new String16FW(Base64.getUrlEncoder().encodeToString("test".getBytes()))))); String text = jsonb.toJson(condition); diff --git a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapterTest.java b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapterTest.java index 6e1596bac5..f6a6fb4165 100644 --- a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapterTest.java +++ b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/config/GrpcKafkaOptionsConfigAdapterTest.java @@ -26,11 +26,11 @@ import org.junit.Before; import org.junit.Test; -import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaCorrelationConfig; -import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaIdempotencyConfig; -import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaOptionsConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaCorrelationConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaIdempotencyConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaOptionsConfig; +import io.aklivity.zilla.runtime.binding.grpc.kafka.config.GrpcKafkaReliabilityConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaOptionsConfigAdapter; -import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.config.GrpcKafkaReliabilityConfig; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.kafka.internal.types.String8FW; diff --git a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaFetchProxyIT.java b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaFetchProxyIT.java index 02c0dc3702..d899699271 100644 --- a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaFetchProxyIT.java +++ b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaFetchProxyIT.java @@ -40,9 +40,7 @@ public class GrpcKafkaFetchProxyIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/kafka/config") diff --git a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaProduceProxyIT.java b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaProduceProxyIT.java index 8645086fcf..1470ed8a24 100644 --- a/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaProduceProxyIT.java +++ b/runtime/binding-grpc-kafka/src/test/java/io/aklivity/zilla/runtime/blinding/grpc/kafka/internal/stream/GrpcKafkaProduceProxyIT.java @@ -39,9 +39,7 @@ public class GrpcKafkaProduceProxyIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/kafka/config") .external("kafka0") diff --git a/runtime/binding-grpc/pom.xml b/runtime/binding-grpc/pom.xml index 680096380f..7bdf8c951c 100644 --- a/runtime/binding-grpc/pom.xml +++ b/runtime/binding-grpc/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcConditionConfig.java similarity index 84% rename from runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionConfig.java rename to runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcConditionConfig.java index d287be644c..dc8e0a3f80 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionConfig.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcConditionConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.config; import java.util.Map; @@ -22,11 +22,11 @@ public final class GrpcConditionConfig extends ConditionConfig { public final String method; - public final Map metadata; + public final Map metadata; public GrpcConditionConfig( String method, - Map metadata) + Map metadata) { this.method = method; this.metadata = metadata; diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcMetadataValueConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcMetadataValueConfig.java new file mode 100644 index 0000000000..c90a8e2023 --- /dev/null +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcMetadataValueConfig.java @@ -0,0 +1,32 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.grpc.config; + +import io.aklivity.zilla.runtime.binding.grpc.internal.types.String16FW; + +public class GrpcMetadataValueConfig +{ + public final String16FW textValue; + public final String16FW base64Value; + + public GrpcMetadataValueConfig( + String16FW textValue, + String16FW base64Value) + { + + this.textValue = textValue; + this.base64Value = base64Value; + } +} diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcMethodConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcMethodConfig.java similarity index 92% rename from runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcMethodConfig.java rename to runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcMethodConfig.java index f2beab572d..47f1e8648a 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcMethodConfig.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcMethodConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.config; public class GrpcMethodConfig diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcOptionsConfig.java similarity index 93% rename from runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfig.java rename to runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcOptionsConfig.java index 06831378e7..e00944534a 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfig.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcOptionsConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.config; import java.util.List; diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcProtobufConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcProtobufConfig.java similarity index 93% rename from runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcProtobufConfig.java rename to runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcProtobufConfig.java index 736b42376d..00426f7747 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcProtobufConfig.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcProtobufConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.config; import java.util.Set; diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcServiceConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcServiceConfig.java similarity index 93% rename from runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcServiceConfig.java rename to runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcServiceConfig.java index 50adada421..2ac7caefce 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcServiceConfig.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/config/GrpcServiceConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.grpc.config; import java.util.Set; diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcBindingConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcBindingConfig.java index 0eba17cec3..323417f06a 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcBindingConfig.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcBindingConfig.java @@ -35,8 +35,8 @@ import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; - - +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcMethodConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcOptionsConfig; import io.aklivity.zilla.runtime.binding.grpc.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.internal.types.HttpHeaderFW; import io.aklivity.zilla.runtime.binding.grpc.internal.types.String16FW; @@ -336,7 +336,7 @@ private long parsePeriod( milliseconds = TimeUnit.SECONDS.toMillis(number); break; case "m": - milliseconds = milliseconds; + milliseconds = TimeUnit.MILLISECONDS.toMillis(number); break; case "u": milliseconds = TimeUnit.MICROSECONDS.toMillis(number); diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionConfigAdapter.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionConfigAdapter.java index 2c1280170d..6c3db67c6f 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionConfigAdapter.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionConfigAdapter.java @@ -26,6 +26,8 @@ import org.agrona.collections.Object2ObjectHashMap; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcConditionConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcMetadataValueConfig; import io.aklivity.zilla.runtime.binding.grpc.internal.GrpcBinding; import io.aklivity.zilla.runtime.binding.grpc.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.grpc.internal.types.String8FW; @@ -87,7 +89,7 @@ public ConditionConfig adaptFromJson( ? object.getJsonObject(METADATA_NAME) : null; - final Map newMetadata = new Object2ObjectHashMap<>(); + final Map newMetadata = new Object2ObjectHashMap<>(); if (metadata != null) { @@ -118,7 +120,7 @@ public ConditionConfig adaptFromJson( throw new IllegalArgumentException("Unexpected type: " + valueType); } - GrpcMetadataValue metadataValue = new GrpcMetadataValue(new String16FW(textValue), + GrpcMetadataValueConfig metadataValue = new GrpcMetadataValueConfig(new String16FW(textValue), new String16FW(base64Value)); newMetadata.put(key, metadataValue); }); diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionMatcher.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionMatcher.java index 8c37b735b6..9ab89f2c0c 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionMatcher.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcConditionMatcher.java @@ -22,6 +22,8 @@ import org.agrona.DirectBuffer; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcConditionConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcMetadataValueConfig; import io.aklivity.zilla.runtime.binding.grpc.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.internal.types.String8FW; import io.aklivity.zilla.runtime.binding.grpc.internal.types.stream.GrpcMetadataFW; @@ -29,7 +31,7 @@ public final class GrpcConditionMatcher { private final Matcher method; - private final Map metadataMatch; + private final Map metadataMatch; public GrpcConditionMatcher( GrpcConditionConfig condition) @@ -47,12 +49,12 @@ public boolean matches( if (metadataMatch != null) { - for (Map.Entry entry : metadataMatch.entrySet()) + for (Map.Entry entry : metadataMatch.entrySet()) { final DirectBuffer name = entry.getKey().value(); final GrpcMetadataFW metadata = metadataHeaders.matchFirst(h -> name.compareTo(h.name().value()) == 0); - final GrpcMetadataValue value = entry.getValue(); + final GrpcMetadataValueConfig value = entry.getValue(); final DirectBuffer matcher = metadata != null && metadata.type().get() == BASE64 ? value.base64Value.value() : value.textValue.value(); diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcMetadataValue.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcMetadataValue.java deleted file mode 100644 index 7321cb1419..0000000000 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcMetadataValue.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.binding.grpc.internal.config; - -import io.aklivity.zilla.runtime.binding.grpc.internal.types.String16FW; - -public class GrpcMetadataValue -{ - public final String16FW textValue; - public final String16FW base64Value; - - public GrpcMetadataValue( - String16FW textValue, - String16FW base64Value) - { - - this.textValue = textValue; - this.base64Value = base64Value; - } -} diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapter.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapter.java index 65d6139706..c2a55f352c 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapter.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapter.java @@ -36,6 +36,9 @@ import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTreeWalker; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcOptionsConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcProtobufConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcServiceConfig; import io.aklivity.zilla.runtime.binding.grpc.internal.GrpcBinding; import io.aklivity.zilla.runtime.binding.grpc.internal.parser.Protobuf3Lexer; import io.aklivity.zilla.runtime.binding.grpc.internal.parser.Protobuf3Parser; @@ -47,7 +50,6 @@ public final class GrpcOptionsConfigAdapter implements OptionsConfigAdapterSpi, { private static final String SERVICES_NAME = "services"; private Function readURL; - private ConfigAdapterContext context; @Override public Kind kind() diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcRouteConfig.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcRouteConfig.java index ffedbce01a..3c20c81ba6 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcRouteConfig.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcRouteConfig.java @@ -19,12 +19,12 @@ import java.util.List; import java.util.function.LongPredicate; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcConditionConfig; import io.aklivity.zilla.runtime.binding.grpc.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.grpc.internal.types.stream.GrpcMetadataFW; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class GrpcRouteConfig extends OptionsConfig +public final class GrpcRouteConfig { public final long id; diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcServiceDefinitionListener.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcServiceDefinitionListener.java index f789fb5ff2..8ca4e97271 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcServiceDefinitionListener.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcServiceDefinitionListener.java @@ -18,6 +18,8 @@ import org.agrona.collections.ObjectHashSet; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcMethodConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcServiceConfig; import io.aklivity.zilla.runtime.binding.grpc.internal.parser.Protobuf3BaseListener; import io.aklivity.zilla.runtime.binding.grpc.internal.parser.Protobuf3Parser; diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcClientFactory.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcClientFactory.java index 5ba88f9ec9..419b50743d 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcClientFactory.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcClientFactory.java @@ -57,6 +57,7 @@ public class GrpcClientFactory implements GrpcStreamFactory { private static final int GRPC_MESSAGE_PADDING = 5; private static final int DATA_FLAG_INIT = 0x02; + private static final int DATA_FLAG_CONT = 0x00; private static final int DATA_FLAG_FIN = 0x01; private final MutableInteger headerOffsetRW = new MutableInteger(); private static final String HTTP_TYPE_NAME = "http"; @@ -753,8 +754,6 @@ private void onNetData( final int reserved = data.reserved(); final OctetsFW payload = data.payload(); - int flags = data.flags(); - assert acknowledge <= sequence; assert sequence >= replySeq; @@ -781,7 +780,7 @@ private void onNetData( .build() : EMPTY_OCTETS; - flags = messageDeferred > 0 ? flags & ~DATA_FLAG_INIT : flags; + int flags = messageDeferred > 0 ? DATA_FLAG_INIT : DATA_FLAG_INIT | DATA_FLAG_FIN; delegate.doAppData(traceId, authorization, budgetId, reserved, flags, buffer, offset + GRPC_MESSAGE_PADDING, payloadSize, dataEx); } @@ -790,7 +789,7 @@ private void onNetData( messageDeferred -= size; assert messageDeferred >= 0; - flags = messageDeferred > 0 ? flags & ~DATA_FLAG_INIT : flags; + int flags = messageDeferred > 0 ? DATA_FLAG_CONT : DATA_FLAG_FIN; delegate.doAppData(traceId, authorization, budgetId, reserved, flags, buffer, offset, size, EMPTY_OCTETS); diff --git a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcServerFactory.java b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcServerFactory.java index a1f43012bc..89848e73e0 100644 --- a/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcServerFactory.java +++ b/runtime/binding-grpc/src/main/java/io/aklivity/zilla/runtime/binding/grpc/internal/stream/GrpcServerFactory.java @@ -69,6 +69,7 @@ public final class GrpcServerFactory implements GrpcStreamFactory { private static final int GRPC_MESSAGE_PADDING = 5; private static final int DATA_FLAG_INIT = 0x02; + private static final int DATA_FLAG_CONT = 0x00; private static final int DATA_FLAG_FIN = 0x01; private static final int EXPIRING_SIGNAL = 1; private static final String HTTP_TYPE_NAME = "http"; @@ -507,7 +508,6 @@ private void onNetData( final long budgetId = data.budgetId(); final int reserved = data.reserved(); final OctetsFW payload = data.payload(); - int flags = data.flags(); assert acknowledge <= sequence; assert sequence >= initialSeq; @@ -537,7 +537,7 @@ private void onNetData( .deferred(messageDeferred) .build() : EMPTY_OCTETS; - flags = messageDeferred > 0 ? flags & ~DATA_FLAG_INIT : flags; + int flags = messageDeferred > 0 ? DATA_FLAG_INIT : DATA_FLAG_INIT | DATA_FLAG_FIN; delegate.doAppData(traceId, authorization, budgetId, reserved, flags, buffer, offset + GRPC_MESSAGE_PADDING, payloadSize, dataEx); } @@ -551,7 +551,7 @@ private void onNetData( messageDeferred -= size; assert messageDeferred >= 0; - flags = messageDeferred > 0 ? flags & ~DATA_FLAG_INIT : flags; + int flags = messageDeferred > 0 ? DATA_FLAG_CONT : DATA_FLAG_FIN; delegate.doAppData(traceId, authorization, budgetId, reserved, flags, buffer, offset, size, EMPTY_OCTETS); diff --git a/runtime/binding-grpc/src/main/moditect/module-info.java b/runtime/binding-grpc/src/main/moditect/module-info.java index e1f6d49c84..f267ffde54 100644 --- a/runtime/binding-grpc/src/main/moditect/module-info.java +++ b/runtime/binding-grpc/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ requires org.antlr.antlr4.runtime; requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.grpc.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.grpc.internal.GrpcBindingFactorySpi; diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapterTest.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapterTest.java index cacad23831..288ada9d69 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapterTest.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/config/GrpcOptionsConfigAdapterTest.java @@ -37,6 +37,10 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcMethodConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcOptionsConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcProtobufConfig; +import io.aklivity.zilla.runtime.binding.grpc.config.GrpcServiceConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; import io.aklivity.zilla.runtime.engine.internal.config.OptionsAdapter; diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/BidiStreamRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/BidiStreamRpcIT.java index 74f70513f6..8e85862b20 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/BidiStreamRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/BidiStreamRpcIT.java @@ -40,9 +40,7 @@ public class BidiStreamRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("net0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ClientStreamRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ClientStreamRpcIT.java index 2930c2efe8..9af46146f3 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ClientStreamRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ClientStreamRpcIT.java @@ -38,9 +38,7 @@ public class ClientStreamRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("net0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ServerStreamRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ServerStreamRpcIT.java index 5aef2410fc..cffb69558f 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ServerStreamRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/ServerStreamRpcIT.java @@ -38,9 +38,7 @@ public class ServerStreamRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("net0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/UnaryRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/UnaryRpcIT.java index 80ecb6867d..7855ea51e3 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/UnaryRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/client/UnaryRpcIT.java @@ -38,9 +38,7 @@ public class UnaryRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("net0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/BidiStreamRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/BidiStreamRpcIT.java index 5959072c6d..69f274b748 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/BidiStreamRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/BidiStreamRpcIT.java @@ -40,9 +40,7 @@ public class BidiStreamRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("app0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ClientStreamRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ClientStreamRpcIT.java index 83d956cdbd..ee467eaed3 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ClientStreamRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ClientStreamRpcIT.java @@ -38,9 +38,7 @@ public class ClientStreamRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("app0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/RejectedRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/RejectedRpcIT.java index 49c6e241c6..5162b7c553 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/RejectedRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/RejectedRpcIT.java @@ -37,9 +37,7 @@ public class RejectedRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("app0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ServerStreamRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ServerStreamRpcIT.java index 9b1a034a32..ba703f6c6c 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ServerStreamRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/ServerStreamRpcIT.java @@ -38,9 +38,7 @@ public class ServerStreamRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("app0") .clean(); diff --git a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/UnaryRpcIT.java b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/UnaryRpcIT.java index 18833d58ed..4ea8a2315a 100644 --- a/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/UnaryRpcIT.java +++ b/runtime/binding-grpc/src/test/java/io/aklivity/zilla/runtime/binding/grpc/internal/streams/server/UnaryRpcIT.java @@ -38,9 +38,7 @@ public class UnaryRpcIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/grpc/config") .external("app0") .clean(); diff --git a/runtime/binding-http-filesystem/pom.xml b/runtime/binding-http-filesystem/pom.xml index d650101c15..2951509679 100644 --- a/runtime/binding-http-filesystem/pom.xml +++ b/runtime/binding-http-filesystem/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfig.java b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/config/HttpFileSystemConditionConfig.java similarity index 92% rename from runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfig.java rename to runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/config/HttpFileSystemConditionConfig.java index 72dac40404..fe70c5b409 100644 --- a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfig.java +++ b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/config/HttpFileSystemConditionConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.http.filesystem.internal.config; +package io.aklivity.zilla.runtime.binding.http.filesystem.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapter.java b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapter.java index a4167556c2..4e9830d78f 100644 --- a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapter.java +++ b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapter.java @@ -19,6 +19,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.http.filesystem.config.HttpFileSystemConditionConfig; import io.aklivity.zilla.runtime.binding.http.filesystem.internal.HttpFileSystemBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; diff --git a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionMatcher.java b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionMatcher.java index 8934184fdc..1e7f576090 100644 --- a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionMatcher.java +++ b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionMatcher.java @@ -18,6 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.http.filesystem.config.HttpFileSystemConditionConfig; + public final class HttpFileSystemConditionMatcher { private final Matcher path; diff --git a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemRouteConfig.java b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemRouteConfig.java index 01838d6e0a..457f18fa73 100644 --- a/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemRouteConfig.java +++ b/runtime/binding-http-filesystem/src/main/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemRouteConfig.java @@ -21,10 +21,10 @@ import java.util.function.Consumer; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.http.filesystem.config.HttpFileSystemConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class HttpFileSystemRouteConfig extends OptionsConfig +public final class HttpFileSystemRouteConfig { public final long id; public final Optional with; diff --git a/runtime/binding-http-filesystem/src/main/moditect/module-info.java b/runtime/binding-http-filesystem/src/main/moditect/module-info.java index 03350365b3..f6e5b37c82 100644 --- a/runtime/binding-http-filesystem/src/main/moditect/module-info.java +++ b/runtime/binding-http-filesystem/src/main/moditect/module-info.java @@ -16,6 +16,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.http.filesystem.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.http.filesystem.internal.HttpFileSystemBindingFactorySpi; diff --git a/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapterTest.java b/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapterTest.java index a3880950d1..c6fa254b76 100644 --- a/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapterTest.java +++ b/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/config/HttpFileSystemConditionConfigAdapterTest.java @@ -26,6 +26,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.http.filesystem.config.HttpFileSystemConditionConfig; + public class HttpFileSystemConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/stream/HttpFileSystemProxyIT.java b/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/stream/HttpFileSystemProxyIT.java index b9786c4e3b..d4787a0e5c 100644 --- a/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/stream/HttpFileSystemProxyIT.java +++ b/runtime/binding-http-filesystem/src/test/java/io/aklivity/zilla/runtime/binding/http/filesystem/internal/stream/HttpFileSystemProxyIT.java @@ -39,9 +39,7 @@ public class HttpFileSystemProxyIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/filesystem/config") .external("filesystem0") diff --git a/runtime/binding-http-kafka/pom.xml b/runtime/binding-http-kafka/pom.xml index 602c0eae65..ca7d696db5 100644 --- a/runtime/binding-http-kafka/pom.xml +++ b/runtime/binding-http-kafka/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfig.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaConditionConfig.java similarity index 93% rename from runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfig.java rename to runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaConditionConfig.java index 43511b4e65..18a69eddde 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfig.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaConditionConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.http.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.http.kafka.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaCorrelationConfig.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaCorrelationConfig.java similarity index 93% rename from runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaCorrelationConfig.java rename to runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaCorrelationConfig.java index 6b0460fbfb..e418bd0de1 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaCorrelationConfig.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaCorrelationConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.http.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.http.kafka.config; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String16FW; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaIdempotencyConfig.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaIdempotencyConfig.java similarity index 92% rename from runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaIdempotencyConfig.java rename to runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaIdempotencyConfig.java index 14d3ec912d..658af4d007 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaIdempotencyConfig.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaIdempotencyConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.http.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.http.kafka.config; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String8FW; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfig.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaOptionsConfig.java similarity index 93% rename from runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfig.java rename to runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaOptionsConfig.java index 7e71cf1266..efb1b23138 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfig.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/config/HttpKafkaOptionsConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.http.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.http.kafka.config; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaBindingConfig.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaBindingConfig.java index 8bd37ec6d5..3f563112a9 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaBindingConfig.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaBindingConfig.java @@ -25,6 +25,7 @@ import org.agrona.AsciiSequenceView; import org.agrona.DirectBuffer; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaOptionsConfig; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.HttpHeaderFW; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String8FW; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapter.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapter.java index 0bca44d78a..c7c4dfff7d 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapter.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapter.java @@ -19,6 +19,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaConditionConfig; import io.aklivity.zilla.runtime.binding.http.kafka.internal.HttpKafkaBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionMatcher.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionMatcher.java index 6b55540ab5..865e6e99cb 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionMatcher.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionMatcher.java @@ -18,6 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaConditionConfig; + public final class HttpKafkaConditionMatcher { private final Matcher method; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapter.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapter.java index 582e610cab..60aee03297 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapter.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapter.java @@ -19,6 +19,9 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaCorrelationConfig; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaIdempotencyConfig; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaOptionsConfig; import io.aklivity.zilla.runtime.binding.http.kafka.internal.HttpKafkaBinding; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String8FW; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaRouteConfig.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaRouteConfig.java index c7a6cbfd7f..0fe8a77de5 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaRouteConfig.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaRouteConfig.java @@ -24,11 +24,12 @@ import java.util.regex.MatchResult; import java.util.stream.Collectors; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaConditionConfig; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaOptionsConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; import io.aklivity.zilla.runtime.engine.util.function.LongObjectBiFunction; -public final class HttpKafkaRouteConfig extends OptionsConfig +public final class HttpKafkaRouteConfig { public final long id; public final HttpKafkaWithResolver with; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithProduceResult.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithProduceResult.java index b27c9fe992..0ac118be56 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithProduceResult.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithProduceResult.java @@ -20,6 +20,7 @@ import org.agrona.DirectBuffer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaCorrelationConfig; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.HttpHeaderFW; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.KafkaAckMode; diff --git a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithResolver.java b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithResolver.java index 9ba9e3ace4..913828184d 100644 --- a/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithResolver.java +++ b/runtime/binding-http-kafka/src/main/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaWithResolver.java @@ -28,6 +28,7 @@ import org.agrona.DirectBuffer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaOptionsConfig; import io.aklivity.zilla.runtime.binding.http.kafka.internal.stream.HttpKafkaEtagHelper; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.HttpHeaderFW; diff --git a/runtime/binding-http-kafka/src/main/moditect/module-info.java b/runtime/binding-http-kafka/src/main/moditect/module-info.java index 58b5fd9052..7bbb7ca55b 100644 --- a/runtime/binding-http-kafka/src/main/moditect/module-info.java +++ b/runtime/binding-http-kafka/src/main/moditect/module-info.java @@ -16,6 +16,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.http.kafka.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.http.kafka.internal.HttpKafkaBindingFactorySpi; diff --git a/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapterTest.java b/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapterTest.java index 70a5021255..3b10e971e2 100644 --- a/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapterTest.java +++ b/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaConditionConfigAdapterTest.java @@ -26,6 +26,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaConditionConfig; + public class HttpKafkaConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapterTest.java b/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapterTest.java index 0d3038589d..f3ed5bc871 100644 --- a/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapterTest.java +++ b/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/config/HttpKafkaOptionsConfigAdapterTest.java @@ -26,6 +26,9 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaCorrelationConfig; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaIdempotencyConfig; +import io.aklivity.zilla.runtime.binding.http.kafka.config.HttpKafkaOptionsConfig; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.http.kafka.internal.types.String8FW; diff --git a/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/stream/HttpKafkaProxyIT.java b/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/stream/HttpKafkaProxyIT.java index ff95fd743d..888c4844a0 100644 --- a/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/stream/HttpKafkaProxyIT.java +++ b/runtime/binding-http-kafka/src/test/java/io/aklivity/zilla/runtime/binding/http/kafka/internal/stream/HttpKafkaProxyIT.java @@ -39,9 +39,7 @@ public class HttpKafkaProxyIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/kafka/config") .external("kafka0") diff --git a/runtime/binding-http/pom.xml b/runtime/binding-http/pom.xml index 3a2bdec2e0..31fed0aee3 100644 --- a/runtime/binding-http/pom.xml +++ b/runtime/binding-http/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpAccessControlConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAccessControlConfig.java similarity index 75% rename from runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpAccessControlConfig.java rename to runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAccessControlConfig.java index b8e87df4e6..539be1037d 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpAccessControlConfig.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAccessControlConfig.java @@ -13,12 +13,13 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.http.internal.config; +package io.aklivity.zilla.runtime.binding.http.config; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig.CROSS_ORIGIN; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig.SAME_ORIGIN; +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.CROSS_ORIGIN; +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.SAME_ORIGIN; import static java.lang.ThreadLocal.withInitial; import static java.util.Collections.unmodifiableSet; +import static java.util.function.Function.identity; import static java.util.regex.Pattern.CASE_INSENSITIVE; import java.net.URI; @@ -42,7 +43,7 @@ public final class HttpAccessControlConfig private static final Pattern HEADERS_PATTERN = Pattern.compile("([^,\\s]+)(:?,\\s*([^,\\\\s]+))*", CASE_INSENSITIVE); private static final ThreadLocal ORIGIN_MATCHER = withInitial(() -> ORIGIN_PATTERN.matcher("")); - private static final ThreadLocal HEADERS_MATCHER = withInitial(() -> HEADERS_PATTERN.matcher("")); + static final ThreadLocal HEADERS_MATCHER = withInitial(() -> HEADERS_PATTERN.matcher("")); private static final ThreadLocal HEADER_BUILDER = ThreadLocal.withInitial(HttpHeaderFW.Builder::new); @@ -82,33 +83,23 @@ public final class HttpAccessControlConfig EXPOSED_RESPONSE_HEADERS = unmodifiableSet(headers); } - public enum HttpPolicyConfig - { - SAME_ORIGIN, - CROSS_ORIGIN - } - public final HttpPolicyConfig policy; public final HttpAllowConfig allow; public final Duration maxAge; public final HttpExposeConfig expose; - public HttpAccessControlConfig( - HttpPolicyConfig policy) + public static HttpAccessControlConfigBuilder builder() { - this.policy = policy; - this.allow = null; - this.maxAge = null; - this.expose = null; + return new HttpAccessControlConfigBuilder<>(identity()); } - public HttpAccessControlConfig( + HttpAccessControlConfig( HttpPolicyConfig policy, HttpAllowConfig allow, Duration maxAge, HttpExposeConfig expose) { - this.policy = CROSS_ORIGIN; + this.policy = policy; this.allow = allow; this.maxAge = maxAge; this.expose = expose; @@ -296,119 +287,7 @@ private boolean matchesAuthority( return matches; } - public static final class HttpAllowConfig - { - public final Set origins; - public final Set methods; - public final Set headers; - public final boolean credentials; - - private final Set implicitOrigins; - - public HttpAllowConfig( - Set origins, - Set methods, - Set headers, - boolean credentials) - { - this.origins = origins; - this.implicitOrigins = origins != null ? asImplicitOrigins(origins) : null; - this.methods = methods; - this.headers = headers != null ? asCaseless(headers) : null; - this.credentials = credentials; - } - - private boolean origin( - String origin) - { - return origins == null || - origins.contains(origin) || - implicitOrigins.contains(origin); - } - - private boolean method( - String method) - { - return methods == null || - methods.contains(method); - } - - private boolean headers( - String headers) - { - return headers == null || - headersMatch(headers); - } - - private boolean headersMatch( - String headers) - { - int match = 0; - - Matcher matchHeaders = HEADERS_MATCHER.get().reset(headers); - while (matchHeaders.find()) - { - if (header(matchHeaders.group(1))) - { - match++; - } - } - - return match > 0; - } - - private boolean header( - String header) - { - return headers == null || - headers.contains(header); - } - - private boolean originExplicit() - { - return credentials || origins != null; - } - - private boolean methodsExplicit() - { - return credentials || methods != null; - } - - private boolean headersExplicit() - { - return credentials || headers != null; - } - - public boolean credentialsExplicit() - { - return credentials; - } - } - - public static final class HttpExposeConfig - { - public final Set headers; - - public HttpExposeConfig( - Set headers) - { - this.headers = headers; - } - - private boolean header( - String header) - { - return headers == null || - headers.contains(header); - } - - private boolean headersExplicit() - { - return headers != null; - } - } - - private static Set asCaseless( + static Set asCaseless( Set cased) { final Set caseless = new TreeSet(String::compareToIgnoreCase); @@ -416,7 +295,7 @@ private static Set asCaseless( return caseless; } - private static Set asImplicitOrigins( + static Set asImplicitOrigins( Set origins) { Set implicit = new LinkedHashSet<>(); diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAccessControlConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAccessControlConfigBuilder.java new file mode 100644 index 0000000000..dc3970344c --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAccessControlConfigBuilder.java @@ -0,0 +1,88 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.time.Duration; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class HttpAccessControlConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private HttpPolicyConfig policy; + private HttpAllowConfig allow; + private Duration maxAge; + private HttpExposeConfig expose; + + HttpAccessControlConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + public Class> thisType() + { + return (Class>) getClass(); + } + + public HttpAccessControlConfigBuilder policy( + HttpPolicyConfig policy) + { + this.policy = policy; + return this; + } + + public HttpAllowConfigBuilder> allow() + { + return new HttpAllowConfigBuilder<>(this::allow); + } + + public HttpAccessControlConfigBuilder maxAge( + Duration maxAge) + { + this.maxAge = maxAge; + return this; + } + + public HttpExposeConfigBuilder> expose() + { + return new HttpExposeConfigBuilder<>(this::expose); + } + + @Override + public T build() + { + return mapper.apply(new HttpAccessControlConfig(policy, allow, maxAge, expose)); + } + + private HttpAccessControlConfigBuilder allow( + HttpAllowConfig allow) + { + this.allow = allow; + return this; + } + + private HttpAccessControlConfigBuilder expose( + HttpExposeConfig expose) + { + this.expose = expose; + return this; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAllowConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAllowConfig.java new file mode 100644 index 0000000000..119cee5fef --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAllowConfig.java @@ -0,0 +1,115 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import static java.util.function.Function.identity; + +import java.util.Set; +import java.util.regex.Matcher; + +public final class HttpAllowConfig +{ + public final Set origins; + public final Set methods; + public final Set headers; + public final boolean credentials; + + private final Set implicitOrigins; + + public static HttpAllowConfigBuilder builder() + { + return new HttpAllowConfigBuilder<>(identity()); + } + + HttpAllowConfig( + Set origins, + Set methods, + Set headers, + boolean credentials) + { + this.origins = origins; + this.implicitOrigins = origins != null ? HttpAccessControlConfig.asImplicitOrigins(origins) : null; + this.methods = methods; + this.headers = headers != null ? HttpAccessControlConfig.asCaseless(headers) : null; + this.credentials = credentials; + } + + boolean origin( + String origin) + { + return origins == null || + origins.contains(origin) || + implicitOrigins.contains(origin); + } + + boolean method( + String method) + { + return methods == null || + methods.contains(method); + } + + boolean headers( + String headers) + { + return headers == null || + headersMatch(headers); + } + + private boolean headersMatch( + String headers) + { + int match = 0; + + Matcher matchHeaders = HttpAccessControlConfig.HEADERS_MATCHER.get().reset(headers); + while (matchHeaders.find()) + { + if (header(matchHeaders.group(1))) + { + match++; + } + } + + return match > 0; + } + + private boolean header( + String header) + { + return headers == null || + headers.contains(header); + } + + boolean originExplicit() + { + return credentials || origins != null; + } + + boolean methodsExplicit() + { + return credentials || methods != null; + } + + boolean headersExplicit() + { + return credentials || headers != null; + } + + boolean credentialsExplicit() + { + return credentials; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAllowConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAllowConfigBuilder.java new file mode 100644 index 0000000000..50e6d6fd4c --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAllowConfigBuilder.java @@ -0,0 +1,91 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class HttpAllowConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private Set origins; + private Set methods; + private Set headers; + private boolean credentials; + + HttpAllowConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public HttpAllowConfigBuilder origin( + String origin) + { + if (origins == null) + { + origins = new LinkedHashSet<>(); + } + origins.add(origin); + return this; + } + + public HttpAllowConfigBuilder method( + String method) + { + if (methods == null) + { + methods = new LinkedHashSet<>(); + } + methods.add(method); + return this; + } + + public HttpAllowConfigBuilder header( + String header) + { + if (headers == null) + { + headers = new LinkedHashSet<>(); + } + headers.add(header); + return this; + } + + public HttpAllowConfigBuilder credentials( + boolean credentials) + { + this.credentials = credentials; + return this; + } + + @Override + public T build() + { + return mapper.apply(new HttpAllowConfig(origins, methods, headers, credentials)); + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAuthorizationConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAuthorizationConfig.java new file mode 100644 index 0000000000..7bb3baefd3 --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAuthorizationConfig.java @@ -0,0 +1,37 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import static java.util.function.Function.identity; + +public final class HttpAuthorizationConfig +{ + public final String name; + public final HttpCredentialsConfig credentials; + + public static HttpAuthorizationConfigBuilder builder() + { + return new HttpAuthorizationConfigBuilder<>(identity()); + } + + HttpAuthorizationConfig( + String name, + HttpCredentialsConfig credentials) + { + this.name = name; + this.credentials = credentials; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAuthorizationConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAuthorizationConfigBuilder.java new file mode 100644 index 0000000000..5f16beb53b --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpAuthorizationConfigBuilder.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class HttpAuthorizationConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String name; + private HttpCredentialsConfig credentials; + + HttpAuthorizationConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public HttpAuthorizationConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public HttpCredentialsConfigBuilder> credentials() + { + return new HttpCredentialsConfigBuilder<>(this::credentials); + } + + @Override + public T build() + { + return mapper.apply(new HttpAuthorizationConfig(name, credentials)); + } + + private HttpAuthorizationConfigBuilder credentials( + HttpCredentialsConfig credentials) + { + this.credentials = credentials; + return this; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpConditionConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpConditionConfig.java new file mode 100644 index 0000000000..aa19a7f7f3 --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpConditionConfig.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.Map; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; + +public final class HttpConditionConfig extends ConditionConfig +{ + public final Map headers; + + public static HttpConditionConfigBuilder builder() + { + return new HttpConditionConfigBuilder<>(HttpConditionConfig.class::cast); + } + + public static HttpConditionConfigBuilder builder( + Function mapper) + { + return new HttpConditionConfigBuilder<>(mapper); + } + + HttpConditionConfig( + Map headers) + { + this.headers = headers; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpConditionConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpConditionConfigBuilder.java new file mode 100644 index 0000000000..fb5d90a04b --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpConditionConfigBuilder.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class HttpConditionConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private Map headers; + + HttpConditionConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public HttpConditionConfigBuilder header( + String name, + String value) + { + if (headers == null) + { + headers = new LinkedHashMap<>(); + } + headers.put(name, value); + return this; + } + + public T build() + { + return mapper.apply(new HttpConditionConfig(headers)); + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpCredentialsConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpCredentialsConfig.java new file mode 100644 index 0000000000..837a8483c3 --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpCredentialsConfig.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import static java.util.function.Function.identity; + +import java.util.List; + +public final class HttpCredentialsConfig +{ + public final List headers; + public final List parameters; + public final List cookies; + + public static HttpCredentialsConfigBuilder builder() + { + return new HttpCredentialsConfigBuilder<>(identity()); + } + + HttpCredentialsConfig( + List headers, + List parameters, + List cookies) + { + this.headers = headers; + this.parameters = parameters; + this.cookies = cookies; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpCredentialsConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpCredentialsConfigBuilder.java new file mode 100644 index 0000000000..1f3aa54517 --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpCredentialsConfigBuilder.java @@ -0,0 +1,98 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.LinkedList; +import java.util.List; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class HttpCredentialsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private List headers; + private List parameters; + private List cookies; + + HttpCredentialsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public HttpPatternConfigBuilder> header() + { + return new HttpPatternConfigBuilder<>(this::header); + } + + public HttpPatternConfigBuilder> parameter() + { + return new HttpPatternConfigBuilder<>(this::parameter); + } + + public HttpPatternConfigBuilder> cookie() + { + return new HttpPatternConfigBuilder<>(this::cookie); + } + + @Override + public T build() + { + return mapper.apply(new HttpCredentialsConfig(headers, parameters, cookies)); + } + + private HttpCredentialsConfigBuilder header( + HttpPatternConfig header) + { + if (headers == null) + { + headers = new LinkedList<>(); + } + headers.add(header); + return this; + } + + private HttpCredentialsConfigBuilder parameter( + HttpPatternConfig parameter) + { + if (parameters == null) + { + parameters = new LinkedList<>(); + } + parameters.add(parameter); + return this; + } + + private HttpCredentialsConfigBuilder cookie( + HttpPatternConfig cookie) + { + if (cookies == null) + { + cookies = new LinkedList<>(); + } + cookies.add(cookie); + return this; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpExposeConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpExposeConfig.java new file mode 100644 index 0000000000..b6d2263582 --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpExposeConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import static java.util.function.Function.identity; + +import java.util.Set; + +public final class HttpExposeConfig +{ + public final Set headers; + + public HttpExposeConfigBuilder builder() + { + return new HttpExposeConfigBuilder<>(identity()); + } + + HttpExposeConfig( + Set headers) + { + this.headers = headers; + } + + boolean header( + String header) + { + return headers == null || + headers.contains(header); + } + + boolean headersExplicit() + { + return headers != null; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpExposeConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpExposeConfigBuilder.java new file mode 100644 index 0000000000..9c393f2e8b --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpExposeConfigBuilder.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class HttpExposeConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private Set headers; + + HttpExposeConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public HttpExposeConfigBuilder header( + String header) + { + if (headers == null) + { + headers = new LinkedHashSet<>(); + } + headers.add(header); + return this; + } + + @Override + public T build() + { + return mapper.apply(new HttpExposeConfig(headers)); + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpOptionsConfig.java similarity index 76% rename from runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfig.java rename to runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpOptionsConfig.java index cd3e53b306..bc0933b546 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfig.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpOptionsConfig.java @@ -13,10 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.http.internal.config; +package io.aklivity.zilla.runtime.binding.http.config; import java.util.Map; import java.util.SortedSet; +import java.util.function.Function; import io.aklivity.zilla.runtime.binding.http.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.http.internal.types.String8FW; @@ -29,7 +30,18 @@ public final class HttpOptionsConfig extends OptionsConfig public final HttpAccessControlConfig access; public final HttpAuthorizationConfig authorization; - public HttpOptionsConfig( + public static HttpOptionsConfigBuilder builder() + { + return new HttpOptionsConfigBuilder<>(HttpOptionsConfig.class::cast); + } + + public static HttpOptionsConfigBuilder builder( + Function mapper) + { + return new HttpOptionsConfigBuilder<>(mapper); + } + + HttpOptionsConfig( SortedSet versions, Map overrides, HttpAccessControlConfig access, diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpOptionsConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpOptionsConfigBuilder.java new file mode 100644 index 0000000000..21c3db207e --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpOptionsConfigBuilder.java @@ -0,0 +1,103 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.binding.http.internal.types.String16FW; +import io.aklivity.zilla.runtime.binding.http.internal.types.String8FW; +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class HttpOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private SortedSet versions; + private Map overrides; + private HttpAccessControlConfig access; + private HttpAuthorizationConfig authorization; + + HttpOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public HttpOptionsConfigBuilder version( + HttpVersion version) + { + if (versions == null) + { + versions = new TreeSet<>(); + } + versions.add(version); + return this; + } + + public HttpOptionsConfigBuilder override( + String8FW name, + String16FW value) + { + if (overrides == null) + { + overrides = new LinkedHashMap<>(); + } + overrides.put(name, value); + return this; + } + + public HttpAccessControlConfigBuilder> access() + { + return new HttpAccessControlConfigBuilder<>(this::access); + } + + public HttpAuthorizationConfigBuilder> authorization() + { + return new HttpAuthorizationConfigBuilder<>(this::authorization); + } + + @Override + public T build() + { + return mapper.apply(new HttpOptionsConfig(versions, overrides, access, authorization)); + } + + private HttpOptionsConfigBuilder authorization( + HttpAuthorizationConfig authorization) + { + this.authorization = authorization; + return this; + } + + private HttpOptionsConfigBuilder access( + HttpAccessControlConfig access) + { + this.access = access; + return this; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPatternConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPatternConfig.java new file mode 100644 index 0000000000..97d22dc90b --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPatternConfig.java @@ -0,0 +1,37 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import static java.util.function.Function.identity; + +public final class HttpPatternConfig +{ + public final String name; + public final String pattern; + + public static HttpPatternConfigBuilder builder() + { + return new HttpPatternConfigBuilder<>(identity()); + } + + HttpPatternConfig( + String name, + String pattern) + { + this.name = name; + this.pattern = pattern; + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPatternConfigBuilder.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPatternConfigBuilder.java new file mode 100644 index 0000000000..5f5dda32e9 --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPatternConfigBuilder.java @@ -0,0 +1,61 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class HttpPatternConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String name; + private String pattern; + + HttpPatternConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public HttpPatternConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public HttpPatternConfigBuilder pattern( + String pattern) + { + this.pattern = pattern; + return this; + } + + @Override + public T build() + { + return mapper.apply(new HttpPatternConfig(name, pattern)); + } +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPolicyConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPolicyConfig.java new file mode 100644 index 0000000000..74a0aa1c93 --- /dev/null +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpPolicyConfig.java @@ -0,0 +1,22 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.http.config; + +public enum HttpPolicyConfig +{ + SAME_ORIGIN, + CROSS_ORIGIN +} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpVersion.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpVersion.java similarity index 94% rename from runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpVersion.java rename to runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpVersion.java index 70510ba4d0..8008b3d1a2 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpVersion.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/config/HttpVersion.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.http.internal.config; +package io.aklivity.zilla.runtime.binding.http.config; public enum HttpVersion { diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpAuthorizationConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpAuthorizationConfig.java deleted file mode 100644 index 51604815e1..0000000000 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpAuthorizationConfig.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.http.internal.config; - -import java.util.List; -import java.util.function.Function; - -public final class HttpAuthorizationConfig -{ - public static final Function, String> DEFAULT_CREDENTIALS = f -> null; - - public final String name; - public final HttpCredentialsConfig credentials; - - public HttpAuthorizationConfig( - String name, - HttpCredentialsConfig credentials) - { - this.name = name; - this.credentials = credentials; - } - - public static final class HttpCredentialsConfig - { - public final List headers; - public final List parameters; - public final List cookies; - - - public HttpCredentialsConfig( - List headers) - { - this(headers, null, null); - } - - public HttpCredentialsConfig( - List headers, - List parameters, - List cookies) - { - this.headers = headers; - this.parameters = parameters; - this.cookies = cookies; - } - } - - public static final class HttpPatternConfig - { - public final String name; - public final String pattern; - - public HttpPatternConfig( - String name, - String pattern) - { - this.name = name; - this.pattern = pattern; - } - } -} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpBindingConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpBindingConfig.java index 2a64bcb2e6..9bbe39aa86 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpBindingConfig.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpBindingConfig.java @@ -15,8 +15,7 @@ */ package io.aklivity.zilla.runtime.binding.http.internal.config; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig.SAME_ORIGIN; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAuthorizationConfig.DEFAULT_CREDENTIALS; +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.SAME_ORIGIN; import static java.util.EnumSet.allOf; import static java.util.stream.Collectors.toList; @@ -28,15 +27,20 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAuthorizationConfig.HttpCredentialsConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAuthorizationConfig.HttpPatternConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpAccessControlConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpCredentialsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpPatternConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpVersion; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; public final class HttpBindingConfig { + private static final Function, String> DEFAULT_CREDENTIALS = f -> null; private static final SortedSet DEFAULT_VERSIONS = new TreeSet<>(allOf(HttpVersion.class)); - private static final HttpAccessControlConfig DEFAULT_ACCESS_CONTROL = new HttpAccessControlConfig(SAME_ORIGIN); + private static final HttpAccessControlConfig DEFAULT_ACCESS_CONTROL = + HttpAccessControlConfig.builder().policy(SAME_ORIGIN).build(); public final long id; public final String name; diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfig.java deleted file mode 100644 index 084a1bea60..0000000000 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfig.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.http.internal.config; - -import java.util.Map; - -import io.aklivity.zilla.runtime.engine.config.ConditionConfig; - -public final class HttpConditionConfig extends ConditionConfig -{ - public final Map headers; - - public HttpConditionConfig( - Map headers) - { - this.headers = headers; - } -} diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapter.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapter.java index 17cc93098f..b259a01dd7 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapter.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapter.java @@ -15,15 +15,14 @@ */ package io.aklivity.zilla.runtime.binding.http.internal.config; -import java.util.LinkedHashMap; -import java.util.Map; - import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; import jakarta.json.JsonString; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.http.config.HttpConditionConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpConditionConfigBuilder; import io.aklivity.zilla.runtime.binding.http.internal.HttpBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; @@ -62,19 +61,14 @@ public JsonObject adaptToJson( public ConditionConfig adaptFromJson( JsonObject object) { - JsonObject headers = object.containsKey(HEADERS_NAME) - ? object.getJsonObject(HEADERS_NAME) - : null; - - Map newHeaders = null; + HttpConditionConfigBuilder httpCondition = HttpConditionConfig.builder(); - if (headers != null) + if (object.containsKey(HEADERS_NAME)) { - Map newHeaders0 = new LinkedHashMap<>(); - headers.forEach((k, v) -> newHeaders0.put(k, JsonString.class.cast(v).getString())); - newHeaders = newHeaders0; + object.getJsonObject(HEADERS_NAME) + .forEach((k, v) -> httpCondition.header(k, JsonString.class.cast(v).getString())); } - return new HttpConditionConfig(newHeaders); + return httpCondition.build(); } } diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionMatcher.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionMatcher.java index 8f1d962c1b..253040c8b3 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionMatcher.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionMatcher.java @@ -21,6 +21,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.http.config.HttpConditionConfig; + public final class HttpConditionMatcher { private final Map headersMatch; diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapter.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapter.java index 1a700f1548..3803b9c771 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapter.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapter.java @@ -15,33 +15,32 @@ */ package io.aklivity.zilla.runtime.binding.http.internal.config; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig.CROSS_ORIGIN; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig.SAME_ORIGIN; +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.CROSS_ORIGIN; +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.SAME_ORIGIN; import java.time.Duration; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; import jakarta.json.Json; -import jakarta.json.JsonArray; import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonNumber; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; import jakarta.json.JsonString; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.http.config.HttpAccessControlConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpAccessControlConfigBuilder; +import io.aklivity.zilla.runtime.binding.http.config.HttpAllowConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpAllowConfigBuilder; +import io.aklivity.zilla.runtime.binding.http.config.HttpAuthorizationConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpAuthorizationConfigBuilder; +import io.aklivity.zilla.runtime.binding.http.config.HttpCredentialsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpCredentialsConfigBuilder; +import io.aklivity.zilla.runtime.binding.http.config.HttpExposeConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpExposeConfigBuilder; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfigBuilder; +import io.aklivity.zilla.runtime.binding.http.config.HttpVersion; import io.aklivity.zilla.runtime.binding.http.internal.HttpBinding; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpAllowConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpExposeConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAuthorizationConfig.HttpCredentialsConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAuthorizationConfig.HttpPatternConfig; import io.aklivity.zilla.runtime.binding.http.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.http.internal.types.String8FW; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; @@ -234,197 +233,144 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - JsonArray versions = object.containsKey(VERSIONS_NAME) - ? object.getJsonArray(VERSIONS_NAME) - : null; + HttpOptionsConfigBuilder httpOptions = HttpOptionsConfig.builder(); - SortedSet newVersions = null; - - if (versions != null) + if (object.containsKey(VERSIONS_NAME)) { - SortedSet newVersions0 = new TreeSet(); - versions.forEach(v -> - newVersions0.add(HttpVersion.of(JsonString.class.cast(v).getString()))); - newVersions = newVersions0; + object.getJsonArray(VERSIONS_NAME) + .forEach(v -> httpOptions.version(HttpVersion.of(JsonString.class.cast(v).getString()))); } - HttpAuthorizationConfig newAuthorization = null; - - JsonObject authorizations = object.containsKey(AUTHORIZATION_NAME) - ? object.getJsonObject(AUTHORIZATION_NAME) - : null; - - if (authorizations != null) + if (object.containsKey(AUTHORIZATION_NAME)) { + HttpAuthorizationConfigBuilder httpAuthorization = httpOptions.authorization(); + + JsonObject authorizations = object.getJsonObject(AUTHORIZATION_NAME); for (String name : authorizations.keySet()) { JsonObject authorization = authorizations.getJsonObject(name); - - HttpCredentialsConfig newCredentials = null; - JsonObject credentials = authorization.getJsonObject(AUTHORIZATION_CREDENTIALS_NAME); if (credentials != null) { - List newHeaders = - adaptPatternFromJson(credentials, AUTHORIZATION_CREDENTIALS_HEADERS_NAME); + HttpCredentialsConfigBuilder httpCredentials = httpAuthorization + .name(name) + .credentials(); - List newParameters = - adaptPatternFromJson(credentials, AUTHORIZATION_CREDENTIALS_QUERY_NAME); + if (credentials.containsKey(AUTHORIZATION_CREDENTIALS_HEADERS_NAME)) + { + credentials.getJsonObject(AUTHORIZATION_CREDENTIALS_HEADERS_NAME) + .forEach((n, v) -> httpCredentials.header() + .name(n) + .pattern(JsonString.class.cast(v).getString()) + .build()); + } - List newCookies = - adaptPatternFromJson(credentials, AUTHORIZATION_CREDENTIALS_COOKIES_NAME); + if (credentials.containsKey(AUTHORIZATION_CREDENTIALS_QUERY_NAME)) + { + credentials.getJsonObject(AUTHORIZATION_CREDENTIALS_QUERY_NAME) + .forEach((n, v) -> httpCredentials.parameter() + .name(n) + .pattern(JsonString.class.cast(v).getString()) + .build()); + } - newCredentials = new HttpCredentialsConfig(newHeaders, newParameters, newCookies); - } + if (credentials.containsKey(AUTHORIZATION_CREDENTIALS_COOKIES_NAME)) + { + credentials.getJsonObject(AUTHORIZATION_CREDENTIALS_COOKIES_NAME) + .forEach((n, v) -> httpCredentials.cookie() + .name(n) + .pattern(JsonString.class.cast(v).getString()) + .build()); + } - newAuthorization = new HttpAuthorizationConfig(name, newCredentials); + httpCredentials.build(); + } } - } - - HttpAccessControlConfig newAccess = null; - JsonObject access = object.containsKey(ACCESS_CONTROL_NAME) - ? object.getJsonObject(ACCESS_CONTROL_NAME) - : null; + httpAuthorization.build(); + } - if (access != null) + if (object.containsKey(ACCESS_CONTROL_NAME)) { - String policy = access.containsKey(POLICY_NAME) - ? access.getString(POLICY_NAME) - : null; + JsonObject access = object.getJsonObject(ACCESS_CONTROL_NAME); - switch (policy) + if (access.containsKey(POLICY_NAME)) { - case POLICY_VALUE_SAME_ORIGIN: - newAccess = new HttpAccessControlConfig(SAME_ORIGIN); - break; - case POLICY_VALUE_CROSS_ORIGIN: - JsonObject allow = access.containsKey(ALLOW_NAME) - ? access.getJsonObject(ALLOW_NAME) - : null; + HttpAccessControlConfigBuilder httpAccess = httpOptions.access(); - HttpAllowConfig newAllow = null; - if (allow != null) + String policy = access.getString(POLICY_NAME); + switch (policy) { - JsonArray origins = allow.containsKey(ALLOW_ORIGINS_NAME) - ? allow.getJsonArray(ALLOW_ORIGINS_NAME) - : null; - - Set newOrigins = null; - if (origins != null) - { - Set newOrigins0 = new LinkedHashSet<>(); - origins.forEach(v -> newOrigins0.add(JsonString.class.cast(v).getString())); - newOrigins = newOrigins0; - } - - JsonArray methods = allow.containsKey(ALLOW_METHODS_NAME) - ? allow.getJsonArray(ALLOW_METHODS_NAME) - : null; + case POLICY_VALUE_SAME_ORIGIN: + httpAccess.policy(SAME_ORIGIN); + break; + case POLICY_VALUE_CROSS_ORIGIN: + httpAccess.policy(CROSS_ORIGIN); - Set newMethods = null; - if (methods != null) + if (access.containsKey(ALLOW_NAME)) { - Set newMethods0 = new LinkedHashSet<>(); - methods.forEach(v -> newMethods0.add(JsonString.class.cast(v).getString())); - newMethods = newMethods0; + HttpAllowConfigBuilder httpAllow = httpAccess.allow(); + JsonObject allow = access.getJsonObject(ALLOW_NAME); + + if (allow.containsKey(ALLOW_ORIGINS_NAME)) + { + allow.getJsonArray(ALLOW_ORIGINS_NAME) + .forEach(v -> httpAllow.origin(JsonString.class.cast(v).getString())); + } + + if (allow.containsKey(ALLOW_METHODS_NAME)) + { + allow.getJsonArray(ALLOW_METHODS_NAME) + .forEach(v -> httpAllow.method(JsonString.class.cast(v).getString())); + } + + if (allow.containsKey(ALLOW_HEADERS_NAME)) + { + allow.getJsonArray(ALLOW_HEADERS_NAME) + .forEach(v -> httpAllow.header(JsonString.class.cast(v).getString())); + } + + if (allow.containsKey(ALLOW_CREDENTIALS_NAME)) + { + httpAllow.credentials(allow.getBoolean(ALLOW_CREDENTIALS_NAME)); + } + + httpAllow.build(); } - JsonArray headers = allow.containsKey(ALLOW_HEADERS_NAME) - ? allow.getJsonArray(ALLOW_HEADERS_NAME) - : null; - - Set newHeaders = null; - if (headers != null) + if (access.containsKey(MAX_AGE_NAME)) { - Set newHeaders0 = new LinkedHashSet<>(); - headers.forEach(v -> newHeaders0.add(JsonString.class.cast(v).getString())); - newHeaders = newHeaders0; + httpAccess.maxAge(Duration.ofSeconds(access.getJsonNumber(MAX_AGE_NAME).longValue())); } - boolean newCredentials = false; - if (allow.containsKey(ALLOW_CREDENTIALS_NAME)) + if (access.containsKey(EXPOSE_NAME)) { - newCredentials = allow.getBoolean(ALLOW_CREDENTIALS_NAME); - } + HttpExposeConfigBuilder httpExpose = httpAccess.expose(); + JsonObject expose = access.getJsonObject(EXPOSE_NAME); - newAllow = new HttpAllowConfig(newOrigins, newMethods, newHeaders, newCredentials); - } + if (expose.containsKey(ALLOW_HEADERS_NAME)) + { + expose.getJsonArray(ALLOW_HEADERS_NAME) + .forEach(v -> httpExpose.header(JsonString.class.cast(v).getString())); + } - Duration newMaxAge = null; - - JsonNumber maxAge = access.containsKey(MAX_AGE_NAME) - ? access.getJsonNumber(MAX_AGE_NAME) - : null; - - if (maxAge != null) - { - newMaxAge = Duration.ofSeconds(maxAge.longValue()); - } - - HttpExposeConfig newExpose = null; - - JsonObject expose = access.containsKey(EXPOSE_NAME) - ? access.getJsonObject(EXPOSE_NAME) - : null; - - if (expose != null) - { - JsonArray headers = expose.containsKey(ALLOW_HEADERS_NAME) - ? expose.getJsonArray(ALLOW_HEADERS_NAME) - : null; - - Set newHeaders = null; - if (headers != null) - { - Set newHeaders0 = new LinkedHashSet<>(); - headers.forEach(v -> newHeaders0.add(JsonString.class.cast(v).getString())); - newHeaders = newHeaders0; + httpExpose.build(); } - newExpose = new HttpExposeConfig(newHeaders); + httpAccess.build(); + break; } - - newAccess = new HttpAccessControlConfig(CROSS_ORIGIN, newAllow, newMaxAge, newExpose); - break; } } - JsonObject overrides = object.containsKey(OVERRIDES_NAME) - ? object.getJsonObject(OVERRIDES_NAME) - : null; - - Map newOverrides = null; - - if (overrides != null) + if (object.containsKey(OVERRIDES_NAME)) { - Map newOverrides0 = new LinkedHashMap<>(); - overrides.forEach((k, v) -> - newOverrides0.put(new String8FW(k), new String16FW(JsonString.class.cast(v).getString()))); - newOverrides = newOverrides0; + object.getJsonObject(OVERRIDES_NAME) + .forEach((k, v) -> + httpOptions.override(new String8FW(k), new String16FW(JsonString.class.cast(v).getString()))); } - return new HttpOptionsConfig(newVersions, newOverrides, newAccess, newAuthorization); - } - - private List adaptPatternFromJson( - JsonObject object, - String property) - { - List newPatterns = null; - if (object.containsKey(property)) - { - newPatterns = new ArrayList<>(); - - JsonObject patterns = object.getJsonObject(property); - for (String name : patterns.keySet()) - { - String pattern = patterns.getString(name); - - newPatterns.add(new HttpPatternConfig(name, pattern)); - } - } - return newPatterns; + return httpOptions.build(); } } diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpRouteConfig.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpRouteConfig.java index 8a5fe931c2..569086176a 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpRouteConfig.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpRouteConfig.java @@ -21,10 +21,10 @@ import java.util.function.Function; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class HttpRouteConfig extends OptionsConfig +public final class HttpRouteConfig { public final long id; diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpClientFactory.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpClientFactory.java index 8660bcc2ff..0088d56060 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpClientFactory.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpClientFactory.java @@ -15,8 +15,8 @@ */ package io.aklivity.zilla.runtime.binding.http.internal.stream; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpVersion.HTTP_1_1; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpVersion.HTTP_2; +import static io.aklivity.zilla.runtime.binding.http.config.HttpVersion.HTTP_1_1; +import static io.aklivity.zilla.runtime.binding.http.config.HttpVersion.HTTP_2; import static io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackContext.TE; import static io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackContext.TRAILERS; import static io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackHeaderFieldFW.HeaderFieldType.UNKNOWN; @@ -63,6 +63,7 @@ import org.agrona.collections.MutableInteger; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.http.config.HttpVersion; import io.aklivity.zilla.runtime.binding.http.internal.HttpBinding; import io.aklivity.zilla.runtime.binding.http.internal.HttpConfiguration; import io.aklivity.zilla.runtime.binding.http.internal.codec.Http2ContinuationFW; @@ -82,7 +83,6 @@ import io.aklivity.zilla.runtime.binding.http.internal.codec.Http2WindowUpdateFW; import io.aklivity.zilla.runtime.binding.http.internal.config.HttpBindingConfig; import io.aklivity.zilla.runtime.binding.http.internal.config.HttpRouteConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpVersion; import io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackContext; import io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackHeaderBlockFW; import io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackHeaderFieldFW; @@ -5061,15 +5061,6 @@ private final class Http2HeadersEncoder { private HpackContext context; - void encodePromise( - HpackContext encodeContext, - Array32FW headers, - HpackHeaderBlockFW.Builder headerBlock) - { - reset(encodeContext); - headers.forEach(h -> headerBlock.header(b -> encodeHeader(h.name(), h.value(), b))); - } - void encodeHeaders( HpackContext encodeContext, Array32FW headers, diff --git a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpServerFactory.java b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpServerFactory.java index 1679cb1172..17fd99f7c4 100644 --- a/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpServerFactory.java +++ b/runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpServerFactory.java @@ -15,7 +15,7 @@ */ package io.aklivity.zilla.runtime.binding.http.internal.stream; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig.CROSS_ORIGIN; +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.CROSS_ORIGIN; import static io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackContext.CONNECTION; import static io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackContext.KEEP_ALIVE; import static io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackContext.PROXY_CONNECTION; @@ -79,6 +79,9 @@ import org.agrona.concurrent.AtomicBuffer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.http.config.HttpAccessControlConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpVersion; import io.aklivity.zilla.runtime.binding.http.internal.HttpBinding; import io.aklivity.zilla.runtime.binding.http.internal.HttpConfiguration; import io.aklivity.zilla.runtime.binding.http.internal.codec.Http2ContinuationFW; @@ -96,11 +99,8 @@ import io.aklivity.zilla.runtime.binding.http.internal.codec.Http2Setting; import io.aklivity.zilla.runtime.binding.http.internal.codec.Http2SettingsFW; import io.aklivity.zilla.runtime.binding.http.internal.codec.Http2WindowUpdateFW; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig; import io.aklivity.zilla.runtime.binding.http.internal.config.HttpBindingConfig; import io.aklivity.zilla.runtime.binding.http.internal.config.HttpRouteConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpVersion; import io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackContext; import io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackHeaderBlockFW; import io.aklivity.zilla.runtime.binding.http.internal.hpack.HpackHeaderFieldFW; @@ -2732,7 +2732,7 @@ private int doRequestData( Flyweight extension) { int requestNoAck = (int)(requestSeq - requestAck); - int length = Math.min(requestMax - requestNoAck - requestPad, limit - offset); + int length = Math.min(Math.max(requestMax - requestNoAck - requestPad, 0), limit - offset); if (length > 0) { @@ -5511,8 +5511,8 @@ private final class Http2Exchange private long requestBud; private int requestCaps; - private BudgetDebitor requestDebitor; - private long requestDebitorIndex = NO_DEBITOR_INDEX; + private BudgetDebitor requestDeb; + private long requestDebIndex = NO_DEBITOR_INDEX; private int localBudget; private int remoteBudget; @@ -5582,10 +5582,10 @@ private void doRequestData( int length = Math.max(Math.min(initialWindow() - requestPad, remaining.value), 0); int reserved = length + requestPad; - if (requestDebitorIndex != NO_DEBITOR_INDEX && requestDebitor != null) + if (requestDebIndex != NO_DEBITOR_INDEX && requestDeb != null) { final int minimum = reserved; // TODO: fragmentation - reserved = requestDebitor.claim(0L, requestDebitorIndex, requestId, minimum, reserved, 0); + reserved = requestDeb.claim(0L, requestDebIndex, requestId, minimum, reserved, 0); length = Math.max(reserved - requestPad, 0); } @@ -5725,10 +5725,10 @@ private void onRequestWindow( requestBud = budgetId; requestCaps = capabilities; - if (requestBud != 0L && requestDebitorIndex == NO_DEBITOR_INDEX) + if (requestBud != 0L && requestDebIndex == NO_DEBITOR_INDEX) { - requestDebitor = supplyDebitor.apply(budgetId); - requestDebitorIndex = requestDebitor.acquire(budgetId, initialId, Http2Server.this::decodeNetworkIfNecessary); + requestDeb = supplyDebitor.apply(budgetId); + requestDebIndex = requestDeb.acquire(budgetId, requestId, Http2Server.this::decodeNetworkIfNecessary); } decodeNetworkIfNecessary(traceId); @@ -5791,10 +5791,10 @@ private void deauthorizeIfNecessary() private void cleanupRequestDebitorIfNecessary() { - if (requestDebitorIndex != NO_DEBITOR_INDEX) + if (requestDebIndex != NO_DEBITOR_INDEX) { - requestDebitor.release(requestDebitorIndex, initialId); - requestDebitorIndex = NO_DEBITOR_INDEX; + requestDeb.release(requestDebIndex, requestId); + requestDebIndex = NO_DEBITOR_INDEX; } } diff --git a/runtime/binding-http/src/main/moditect/module-info.java b/runtime/binding-http/src/main/moditect/module-info.java index 2bc7a266b0..6f1b960854 100644 --- a/runtime/binding-http/src/main/moditect/module-info.java +++ b/runtime/binding-http/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.http.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.http.internal.HttpBindingFactorySpi; diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapterTest.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapterTest.java index ce24884700..4be0bc20a7 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapterTest.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpConditionConfigAdapterTest.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.binding.http.internal.config; import static java.util.Collections.singletonMap; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -28,6 +29,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.http.config.HttpConditionConfig; + public class HttpConditionConfigAdapterTest { private Jsonb jsonb; @@ -60,7 +63,10 @@ public void shouldReadCondition() @Test public void shouldWriteCondition() { - HttpConditionConfig condition = new HttpConditionConfig(singletonMap(":authority", "example.net:443")); + HttpConditionConfig condition = HttpConditionConfig.builder() + .inject(identity()) + .header(":authority", "example.net:443") + .build(); String text = jsonb.toJson(condition); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapterTest.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapterTest.java index 0f400c028c..a9c8c60e6c 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapterTest.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/config/HttpOptionsConfigAdapterTest.java @@ -15,10 +15,10 @@ */ package io.aklivity.zilla.runtime.binding.http.internal.config; -import static io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpPolicyConfig.CROSS_ORIGIN; +import static io.aklivity.zilla.runtime.binding.http.config.HttpPolicyConfig.CROSS_ORIGIN; import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; @@ -28,7 +28,6 @@ import java.time.Duration; import java.util.EnumSet; -import java.util.TreeSet; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; @@ -37,10 +36,8 @@ import org.junit.Before; import org.junit.Test; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpAllowConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAccessControlConfig.HttpExposeConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAuthorizationConfig.HttpCredentialsConfig; -import io.aklivity.zilla.runtime.binding.http.internal.config.HttpAuthorizationConfig.HttpPatternConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpOptionsConfig; +import io.aklivity.zilla.runtime.binding.http.config.HttpVersion; import io.aklivity.zilla.runtime.binding.http.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.http.internal.types.String8FW; @@ -128,25 +125,39 @@ public void shouldReadOptions() @Test public void shouldWriteOptions() { - HttpOptionsConfig options = new HttpOptionsConfig( - new TreeSet<>(EnumSet.allOf(HttpVersion.class)), - singletonMap(new String8FW(":authority"), new String16FW("example.com:443")), - new HttpAccessControlConfig( - CROSS_ORIGIN, - new HttpAllowConfig( - singleton("https://example.com:9090"), - singleton("DELETE"), - singleton("x-api-key"), - true), - Duration.ofSeconds(10), - new HttpExposeConfig( - singleton("x-custom-header"))), - new HttpAuthorizationConfig( - "test0", - new HttpCredentialsConfig( - singletonList(new HttpPatternConfig( - "authorization", - "Bearer {credentials}"))))); + HttpOptionsConfig options = HttpOptionsConfig.builder() + .inject(identity()) + .version(HttpVersion.HTTP_1_1) + .version(HttpVersion.HTTP_2) + .override(new String8FW(":authority"), new String16FW("example.com:443")) + .access() + .inject(identity()) + .policy(CROSS_ORIGIN) + .allow() + .inject(identity()) + .origin("https://example.com:9090") + .method("DELETE") + .header("x-api-key") + .credentials(true) + .build() + .maxAge(Duration.ofSeconds(10)) + .expose() + .inject(identity()) + .header("x-custom-header") + .build() + .build() + .authorization() + .name("test0") + .credentials() + .inject(identity()) + .header() + .inject(identity()) + .name("authorization") + .pattern("Bearer {credentials}") + .build() + .build() + .build() + .build(); String text = jsonb.toJson(options); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/AdvisoryIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/AdvisoryIT.java index bb97ccc902..e5ccfac394 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/AdvisoryIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/AdvisoryIT.java @@ -39,9 +39,7 @@ public class AdvisoryIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("net0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ArchitectureIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ArchitectureIT.java index a931329dd0..ea7f3326dc 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ArchitectureIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ArchitectureIT.java @@ -39,9 +39,7 @@ public class ArchitectureIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("net0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementIT.java index 7616897362..bac31467bb 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementIT.java @@ -40,9 +40,7 @@ public class ConnectionManagementIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("net0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementPoolSize1IT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementPoolSize1IT.java index 376c3c4f2e..0bfb9fa8c5 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementPoolSize1IT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/ConnectionManagementPoolSize1IT.java @@ -42,9 +42,7 @@ public class ConnectionManagementPoolSize1IT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_MAXIMUM_CONNECTIONS, 1) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlIT.java index b72089dba0..65f3fdb5be 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlIT.java @@ -41,9 +41,7 @@ public class FlowControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("net0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlLimitsIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlLimitsIT.java index dc7ff8580d..0ccfea3b2c 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlLimitsIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/FlowControlLimitsIT.java @@ -44,9 +44,7 @@ public class FlowControlLimitsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 128) .configure(ENGINE_BUFFER_POOL_CAPACITY, 256) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/MessageFormatIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/MessageFormatIT.java index 7fda71e3f5..b577942d4b 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/MessageFormatIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/MessageFormatIT.java @@ -40,9 +40,7 @@ public class MessageFormatIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("net0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/TransferCodingsIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/TransferCodingsIT.java index 134b0653e3..7cabe02091 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/TransferCodingsIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/client/TransferCodingsIT.java @@ -40,9 +40,7 @@ public class TransferCodingsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("net0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AccessControlIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AccessControlIT.java index 3b98c45f60..8fd94f97c2 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AccessControlIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AccessControlIT.java @@ -40,9 +40,7 @@ public class AccessControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .configure(HTTP_SERVER_HEADER, "Zilla") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AdvisoryIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AdvisoryIT.java index 01615d1061..e85ab6db08 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AdvisoryIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AdvisoryIT.java @@ -39,9 +39,7 @@ public class AdvisoryIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("app0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ArchitectureIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ArchitectureIT.java index 19ddfac250..363a854e9a 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ArchitectureIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ArchitectureIT.java @@ -39,9 +39,7 @@ public class ArchitectureIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("app0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AuthorizationIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AuthorizationIT.java index 4732b44627..ff8b624f9a 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AuthorizationIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AuthorizationIT.java @@ -40,9 +40,7 @@ public class AuthorizationIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_SERVER_HEADER, "Zilla") .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ConnectionManagementIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ConnectionManagementIT.java index 05390d81c5..6fc76b884c 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ConnectionManagementIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/ConnectionManagementIT.java @@ -40,9 +40,7 @@ public class ConnectionManagementIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("app0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlIT.java index 780705a4d4..10825ce156 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlIT.java @@ -41,9 +41,7 @@ public class FlowControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("app0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlLimitsIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlLimitsIT.java index cccf33682b..65b32aa182 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlLimitsIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/FlowControlLimitsIT.java @@ -41,9 +41,7 @@ public class FlowControlLimitsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 64) .configure(ENGINE_BUFFER_POOL_CAPACITY, 64) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/MessageFormatIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/MessageFormatIT.java index 2e7c45e5a4..221369ca1e 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/MessageFormatIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/MessageFormatIT.java @@ -42,9 +42,7 @@ public class MessageFormatIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/TransferCodingsIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/TransferCodingsIT.java index de4e5ea259..a8808b7794 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/TransferCodingsIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/TransferCodingsIT.java @@ -40,9 +40,7 @@ public class TransferCodingsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v1.1") .external("app0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/AbortIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/AbortIT.java index 51e4706ebe..4dbd2f566f 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/AbortIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/AbortIT.java @@ -42,9 +42,7 @@ public class AbortIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("net0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConfigIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConfigIT.java index 2c93f31985..37eac77678 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConfigIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConfigIT.java @@ -45,9 +45,7 @@ public class ConfigIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configure(EngineConfiguration.ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConnectionManagementIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConnectionManagementIT.java index 606d8e8592..47f2198b76 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConnectionManagementIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/ConnectionManagementIT.java @@ -44,9 +44,7 @@ public class ConnectionManagementIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/FlowControlIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/FlowControlIT.java index ec6087d45f..213c9ce76d 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/FlowControlIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/FlowControlIT.java @@ -43,9 +43,7 @@ public class FlowControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("net0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/MessageFormatIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/MessageFormatIT.java index bf07492bb4..aa747d0f1c 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/MessageFormatIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/MessageFormatIT.java @@ -43,9 +43,7 @@ public class MessageFormatIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("net0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java index c893a08e85..83411f0191 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java @@ -43,9 +43,7 @@ public class StartingIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/upgrade") .external("net0") .configure(EngineConfiguration.ENGINE_DRAIN_ON_CLOSE, false) diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AbortIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AbortIT.java index b94ebf6b40..68cb56238e 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AbortIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AbortIT.java @@ -40,9 +40,7 @@ public class AbortIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AccessControlIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AccessControlIT.java index bb91e2b9d8..ecddd20bbc 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AccessControlIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AccessControlIT.java @@ -41,9 +41,7 @@ public class AccessControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configure(HTTP_SERVER_HEADER, "Zilla") .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AuthorizationIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AuthorizationIT.java index d7c4949856..1a9bfa6755 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AuthorizationIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AuthorizationIT.java @@ -41,9 +41,7 @@ public class AuthorizationIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configure(HTTP_SERVER_HEADER, "Zilla") .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConfigIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConfigIT.java index 300ce1ab0f..082847bf70 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConfigIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConfigIT.java @@ -42,9 +42,7 @@ public class ConfigIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConnectionManagementIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConnectionManagementIT.java index 2c47d46bba..531c9a13ff 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConnectionManagementIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/ConnectionManagementIT.java @@ -44,9 +44,7 @@ public class ConnectionManagementIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/FlowControlIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/FlowControlIT.java index b713e2841f..b45464732e 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/FlowControlIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/FlowControlIT.java @@ -41,9 +41,7 @@ public class FlowControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/MessageFormatIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/MessageFormatIT.java index 2b84809dc2..00340a25a9 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/MessageFormatIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/MessageFormatIT.java @@ -40,9 +40,7 @@ public class MessageFormatIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(HTTP_CONCURRENT_STREAMS, 100) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("app0") diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/SettingsIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/SettingsIT.java index b8946d6977..da3941ca56 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/SettingsIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/SettingsIT.java @@ -41,9 +41,7 @@ public class SettingsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/v2") .external("app0") .clean(); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/StartingIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/StartingIT.java index 890bebc4ab..4741673d7a 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/StartingIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/StartingIT.java @@ -41,9 +41,7 @@ public class StartingIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/http/config/upgrade") .configure(HTTP_CONCURRENT_STREAMS, 100) .external("app0") diff --git a/runtime/binding-kafka-grpc/pom.xml b/runtime/binding-kafka-grpc/pom.xml index 157364901c..e33d6edcae 100644 --- a/runtime/binding-kafka-grpc/pom.xml +++ b/runtime/binding-kafka-grpc/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml @@ -26,7 +26,7 @@ 11 11 - 0.86 + 0.85 0 diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfig.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcConditionConfig.java similarity index 96% rename from runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfig.java rename to runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcConditionConfig.java index 2c35c77412..2a734509d3 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfig.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcConditionConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.grpc.config; import java.util.Map; import java.util.Optional; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcCorrelationConfig.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcCorrelationConfig.java similarity index 94% rename from runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcCorrelationConfig.java rename to runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcCorrelationConfig.java index beb3079c0b..37b41ff7f4 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcCorrelationConfig.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcCorrelationConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.grpc.config; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String16FW; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcIdempotencyConfig.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcIdempotencyConfig.java similarity index 92% rename from runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcIdempotencyConfig.java rename to runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcIdempotencyConfig.java index 8cb93014b2..ab4ecd0cdd 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcIdempotencyConfig.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcIdempotencyConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.grpc.config; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String8FW; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfig.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcOptionsConfig.java similarity index 94% rename from runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfig.java rename to runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcOptionsConfig.java index 2685689b17..3293a1169f 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfig.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/config/KafkaGrpcOptionsConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.grpc.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.grpc.config; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.KafkaAckMode; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcBindingConfig.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcBindingConfig.java index b5490eb300..791c449c42 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcBindingConfig.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcBindingConfig.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Optional; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcOptionsConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.stream.KafkaGrpcFetchHeaderHelper; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapter.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapter.java index 373bb4cbc1..e7bf19e7f7 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapter.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapter.java @@ -26,6 +26,7 @@ import org.agrona.collections.Object2ObjectHashMap; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcConditionConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.KafkaGrpcBinding; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String8FW; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResolver.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResolver.java index 9760e7ddfd..9f98b1ded9 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResolver.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResolver.java @@ -19,6 +19,8 @@ import org.agrona.DirectBuffer; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcConditionConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcOptionsConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.KafkaAckMode; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String16FW; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResult.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResult.java index d7bdb95203..6f051e90b8 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResult.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionResult.java @@ -18,6 +18,7 @@ import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcCorrelationConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.KafkaAckMode; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.KafkaAckModeFW; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapter.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapter.java index d6d41192ee..1564c6af28 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapter.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapter.java @@ -21,6 +21,9 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcCorrelationConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcIdempotencyConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcOptionsConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.KafkaGrpcBinding; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.KafkaAckMode; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String16FW; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcRouteConfig.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcRouteConfig.java index ba54ba363f..d95db803e0 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcRouteConfig.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcRouteConfig.java @@ -19,10 +19,11 @@ import java.util.List; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcConditionConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcOptionsConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class KafkaGrpcRouteConfig extends OptionsConfig +public final class KafkaGrpcRouteConfig { public final long id; public final KafkaGrpcWithConfig with; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcFetchHeaderHelper.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcFetchHeaderHelper.java index 93a29e0e7f..b9a9b6ba60 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcFetchHeaderHelper.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcFetchHeaderHelper.java @@ -18,7 +18,7 @@ import java.util.Map; import java.util.function.Consumer; -import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.config.KafkaGrpcCorrelationConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcCorrelationConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.KafkaHeaderFW; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.OctetsFW; diff --git a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerFactory.java b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerFactory.java index 16bce0db88..baa6d57abb 100644 --- a/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerFactory.java +++ b/runtime/binding-kafka-grpc/src/main/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerFactory.java @@ -69,6 +69,7 @@ public final class KafkaGrpcRemoteServerFactory implements KafkaGrpcStreamFactor private static final String KAFKA_TYPE_NAME = "kafka"; private static final int SIGNAL_INITIATE_KAFKA_STREAM = 1; + private static final int GRPC_QUEUE_MESSAGE_PADDING = 3 * 256 + 33; private static final int DATA_FLAG_COMPLETE = 0x03; private static final int DATA_FLAG_INIT = 0x02; @@ -260,7 +261,7 @@ private KafkaRemoteServer( this.replyAck = 0; this.replyMax = bufferPool.slotCapacity(); this.replyBud = 0; - this.replyPad = 0; + this.replyPad = GRPC_QUEUE_MESSAGE_PADDING; this.replyCap = 0; this.errorProducer = new KafkaErrorProducer(originId, routedId, condition, this); this.grpcClients = new Object2ObjectHashMap<>(); @@ -434,7 +435,8 @@ private void onKafkaData( helper.replyTo, newCorrelationId); } - flushGrpcClientData(grpcClient, traceId, authorization, helper.service, helper.method, flags, payload); + flushGrpcClientData(grpcClient, traceId, authorization, helper.service, helper.method, flags, + reserved, payload); } else if (helper.correlationId != null) { @@ -446,7 +448,8 @@ else if (helper.correlationId != null) GrpcClient grpcClient = grpcClients.get(lastCorrelationId); if (grpcClient != null) { - flushGrpcClientData(grpcClient, traceId, authorization, null, null, flags, payload); + flushGrpcClientData(grpcClient, traceId, authorization, null, null, flags, + reserved, payload); } } @@ -489,12 +492,13 @@ private void flushGrpcMessagesIfBuffered( final long messageTraceId = queueMessage.traceId(); final long messageAuthorization = queueMessage.authorization(); final int flags = queueMessage.flags(); - final int messageSize = queueMessage.valueLength(); + final int reserved = queueMessage.reserved(); + final int valueLength = queueMessage.valueLength(); final OctetsFW payload = queueMessage.value(); final int queuedMessageSize = queueMessage.sizeof(); final int oldProgressOffset = progressOffset; - progressOffset += queuedMessageSize; + progressOffset = queueMessage.limit(); if (correlationId.equals(messageCorrelationId)) { @@ -505,18 +509,19 @@ private void flushGrpcMessagesIfBuffered( final int progress = grpcClient.onKafkaData(messageTraceId, messageAuthorization, flags, payload); - if (progress == messageSize) + if (progress == valueLength) { + replyReserved -= reserved; final int remaining = grpcQueueSlotOffset - progressOffset; grpcQueueBuffer.putBytes(oldProgressOffset, grpcQueueBuffer, progressOffset, remaining); - grpcQueueSlotOffset = grpcQueueSlotOffset - progressOffset; + grpcQueueSlotOffset = oldProgressOffset + remaining; progressOffset = oldProgressOffset; } else if (progress > 0) { final int remainingPayload = queuedMessageSize - progress; - queueGrpcMessage(traceId, authorization, lastCorrelationId, service, method, flags, + queueGrpcMessage(traceId, authorization, lastCorrelationId, service, method, flags, reserved, payload, remainingPayload); final int remainingMessageOffset = grpcQueueSlotOffset - progressOffset; grpcQueueBuffer.putBytes(oldProgressOffset, grpcQueueBuffer, progressOffset, remainingMessageOffset); @@ -542,17 +547,26 @@ private void flushGrpcClientData( OctetsFW service, OctetsFW method, int flags, + int reserved, OctetsFW payload) { final int progress = grpcClient.onKafkaData(traceId, authorization, flags, payload); int length = payload != null ? payload.sizeof() : 0; final int remaining = length - progress; - if (remaining > 0 || payload == null) + + if (remaining == 0 && payload != null || + payload == null && KafkaGrpcState.initialClosing(grpcClient.state)) + { + replyReserved -= reserved; + } + + if (remaining > 0 && payload != null || + payload == null && !KafkaGrpcState.initialClosing(grpcClient.state)) { flags = progress == 0 ? flags : DATA_FLAG_CON; payload = payload == null ? emptyRO : payload; queueGrpcMessage(traceId, authorization, grpcClient.correlationId, service, method, - flags, payload, remaining); + flags, reserved, payload, remaining); } } @@ -563,6 +577,7 @@ private void queueGrpcMessage( OctetsFW service, OctetsFW method, int flags, + int reserved, OctetsFW payload, int length) { @@ -576,6 +591,7 @@ private void queueGrpcMessage( .traceId(traceId) .authorization(authorization) .flags(flags) + .reserved(reserved) .value(payload.buffer(), payload.offset(), length) .build(); @@ -684,14 +700,11 @@ private void doKafkaWindow( { long replyAckMax = Math.max(replySeq - replyReserved, replyAck); - if (replyWindow() - replyAckMax > 0) - { - replyAck = replyAckMax; - assert replyAck <= replySeq; + replyAck = replyAckMax; + assert replyAck <= replySeq; - doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, replyBud, replyPad, replyCap); - } + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBud, replyPad, replyCap); } } @@ -1600,7 +1613,6 @@ private void doGrpcData( traceId, authorization, budgetId, reserved, flags, buffer, offset, length, emptyRO); initialSeq += reserved; - server.replyReserved -= length; assert initialSeq <= initialAck + initialMax; } diff --git a/runtime/binding-kafka-grpc/src/main/moditect/module-info.java b/runtime/binding-kafka-grpc/src/main/moditect/module-info.java index f2019f0684..5b04be2b59 100644 --- a/runtime/binding-kafka-grpc/src/main/moditect/module-info.java +++ b/runtime/binding-kafka-grpc/src/main/moditect/module-info.java @@ -16,6 +16,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.kafka.grpc.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.kafka.grpc.internal.KafkaGrpcBindingFactorySpi; diff --git a/runtime/binding-kafka-grpc/src/main/zilla/internal.idl b/runtime/binding-kafka-grpc/src/main/zilla/internal.idl index 49daf490d6..7ed5eb03e5 100644 --- a/runtime/binding-kafka-grpc/src/main/zilla/internal.idl +++ b/runtime/binding-kafka-grpc/src/main/zilla/internal.idl @@ -27,6 +27,7 @@ scope internal int64 traceId; int64 authorization; uint8 flags = 3; // 0x01 FIN, 0x02 INIT, 0x04 INCOMPLETE, 0x08 SKIP + int32 reserved; int32 valueLength; octets[valueLength] value = null; } diff --git a/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapterTest.java b/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapterTest.java index 8fbfc5ee3d..b341a92d7a 100644 --- a/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapterTest.java +++ b/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcConditionConfigAdapterTest.java @@ -28,6 +28,7 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcConditionConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String8FW; diff --git a/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapterTest.java b/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapterTest.java index 3b22b93365..e5dae6f437 100644 --- a/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapterTest.java +++ b/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/config/KafkaGrpcOptionsConfigAdapterTest.java @@ -27,6 +27,9 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcCorrelationConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcIdempotencyConfig; +import io.aklivity.zilla.runtime.binding.kafka.grpc.config.KafkaGrpcOptionsConfig; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.kafka.grpc.internal.types.String8FW; diff --git a/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerIT.java b/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerIT.java index e09442f13a..928283cce0 100644 --- a/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerIT.java +++ b/runtime/binding-kafka-grpc/src/test/java/io/aklivity/zilla/runtime/binding/kafka/grpc/internal/stream/KafkaGrpcRemoteServerIT.java @@ -40,9 +40,7 @@ public class KafkaGrpcRemoteServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/grpc/config") diff --git a/runtime/binding-kafka/pom.xml b/runtime/binding-kafka/pom.xml index 0cdde14111..e6911fcf34 100644 --- a/runtime/binding-kafka/pom.xml +++ b/runtime/binding-kafka/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml @@ -26,7 +26,7 @@ 11 11 - 0.80 + 0.79 3 diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfig.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaConditionConfig.java similarity index 83% rename from runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfig.java rename to runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaConditionConfig.java index d217d16ea9..e7a22427cf 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfig.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaConditionConfig.java @@ -13,17 +13,20 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; public final class KafkaConditionConfig extends ConditionConfig { public final String topic; + public final String groupId; public KafkaConditionConfig( - String topic) + String topic, + String groupId) { this.topic = topic; + this.groupId = groupId; } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfig.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaOptionsConfig.java similarity index 94% rename from runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfig.java rename to runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaOptionsConfig.java index e556f89b45..a19b7854f9 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfig.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaOptionsConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.config; import java.util.List; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaSaslConfig.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaSaslConfig.java similarity index 94% rename from runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaSaslConfig.java rename to runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaSaslConfig.java index 8e8a5b8097..4860089a0c 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaSaslConfig.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaSaslConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.config; public class KafkaSaslConfig { diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaTopicConfig.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaTopicConfig.java similarity index 96% rename from runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaTopicConfig.java rename to runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaTopicConfig.java index e9204fddac..a688ee438b 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaTopicConfig.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/config/KafkaTopicConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.kafka.config; import java.util.Objects; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/KafkaConfiguration.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/KafkaConfiguration.java index d9cf0a1d04..f70dadadc7 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/KafkaConfiguration.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/KafkaConfiguration.java @@ -20,9 +20,12 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.reflect.Method; import java.math.BigInteger; import java.nio.file.Path; import java.security.SecureRandom; +import java.time.Duration; +import java.util.UUID; import java.util.function.Supplier; import org.agrona.LangUtil; @@ -63,12 +66,19 @@ public class KafkaConfiguration extends Configuration public static final IntPropertyDef KAFKA_CACHE_CLIENT_TRAILERS_SIZE_MAX; public static final IntPropertyDef KAFKA_CACHE_SERVER_RECONNECT_DELAY; public static final PropertyDef KAFKA_CLIENT_SASL_SCRAM_NONCE; + public static final PropertyDef KAFKA_CLIENT_GROUP_REBALANCE_TIMEOUT; + public static final PropertyDef KAFKA_CLIENT_ID; + public static final PropertyDef KAFKA_CLIENT_INSTANCE_ID; + public static final BooleanPropertyDef KAFKA_CLIENT_CONNECTION_POOL; private static final ConfigurationDef KAFKA_CONFIG; static { final ConfigurationDef config = new ConfigurationDef("zilla.binding.kafka"); + KAFKA_CLIENT_ID = config.property("client.id", "zilla"); + KAFKA_CLIENT_INSTANCE_ID = config.property(InstanceIdSupplier.class, "client.instance.id", + KafkaConfiguration::decodeInstanceId, KafkaConfiguration::defaultInstanceId); KAFKA_CLIENT_MAX_IDLE_MILLIS = config.property("client.max.idle.ms", 1 * 60 * 1000); KAFKA_CLIENT_META_MAX_AGE_MILLIS = config.property("client.meta.max.age.ms", 5 * 60 * 1000); KAFKA_CLIENT_DESCRIBE_MAX_AGE_MILLIS = config.property("client.describe.max.age.ms", 5 * 60 * 1000); @@ -78,6 +88,10 @@ public class KafkaConfiguration extends Configuration KAFKA_CLIENT_PRODUCE_MAX_REQUEST_MILLIS = config.property("client.produce.max.request.millis", 0); KAFKA_CLIENT_PRODUCE_MAX_RESPONSE_MILLIS = config.property("client.produce.max.response.millis", 120000); KAFKA_CLIENT_PRODUCE_MAX_BYTES = config.property("client.produce.max.bytes", Integer.MAX_VALUE); + KAFKA_CLIENT_SASL_SCRAM_NONCE = config.property(NonceSupplier.class, "client.sasl.scram.nonce", + KafkaConfiguration::decodeNonceSupplier, KafkaConfiguration::defaultNonceSupplier); + KAFKA_CLIENT_GROUP_REBALANCE_TIMEOUT = config.property(Duration.class, "client.group.rebalance.timeout", + (c, v) -> Duration.parse(v), "PT4S"); KAFKA_CACHE_DIRECTORY = config.property(Path.class, "cache.directory", KafkaConfiguration::cacheDirectory, KafkaBinding.NAME); KAFKA_CACHE_SERVER_BOOTSTRAP = config.property("cache.server.bootstrap", true); @@ -98,8 +112,7 @@ public class KafkaConfiguration extends Configuration KAFKA_CACHE_SEGMENT_BYTES = config.property("cache.segment.bytes", 0x40000000); KAFKA_CACHE_SEGMENT_INDEX_BYTES = config.property("cache.segment.index.bytes", 0xA00000); KAFKA_CACHE_CLIENT_TRAILERS_SIZE_MAX = config.property("cache.client.trailers.size.max", 256); - KAFKA_CLIENT_SASL_SCRAM_NONCE = config.property(NonceSupplier.class, "client.sasl.scram.nonce", - KafkaConfiguration::decodeNonceSupplier, KafkaConfiguration::defaultNonceSupplier); + KAFKA_CLIENT_CONNECTION_POOL = config.property("client.connection.pool", true); KAFKA_CONFIG = config; } @@ -229,6 +242,11 @@ public boolean cacheServerBootstrap() return KAFKA_CACHE_SERVER_BOOTSTRAP.getAsBoolean(this); } + public boolean clientConnectionPool() + { + return KAFKA_CLIENT_CONNECTION_POOL.getAsBoolean(this); + } + public int cacheClientReconnect() { return KAFKA_CACHE_CLIENT_RECONNECT_DELAY.getAsInt(this); @@ -248,6 +266,16 @@ public int cacheClientTrailersSizeMax() return KAFKA_CACHE_CLIENT_TRAILERS_SIZE_MAX.getAsInt(this); } + public String clientId() + { + return KAFKA_CLIENT_ID.get(this); + } + + public Duration clientGroupRebalanceTimeout() + { + return KAFKA_CLIENT_GROUP_REBALANCE_TIMEOUT.get(this); + } + private static Path cacheDirectory( Configuration config, String cacheDirectory) @@ -267,6 +295,11 @@ public Supplier nonceSupplier() return KAFKA_CLIENT_SASL_SCRAM_NONCE.get(this)::get; } + public Supplier clientInstanceIdSupplier() + { + return KAFKA_CLIENT_INSTANCE_ID.get(this)::get; + } + @FunctionalInterface private interface NonceSupplier { @@ -274,8 +307,7 @@ private interface NonceSupplier } private static NonceSupplier decodeNonceSupplier( - Configuration config, - String value) + String value) { NonceSupplier supplier = null; @@ -309,10 +341,59 @@ private static NonceSupplier decodeNonceSupplier( return supplier; } - private static NonceSupplier defaultNonceSupplier( - Configuration config) + private static String defaultNonceSupplier() + { + return new BigInteger(130, new SecureRandom()).toString(Character.MAX_RADIX); + } + + @FunctionalInterface + private interface InstanceIdSupplier extends Supplier + { + } + + private static InstanceIdSupplier decodeInstanceId( + Configuration config, + String value) + { + try + { + String className = value.substring(0, value.indexOf("$$Lambda")); + Class lambdaClass = Class.forName(className); + + Method targetMethod = null; + for (Method method : lambdaClass.getDeclaredMethods()) + { + if (method.isSynthetic()) + { + targetMethod = method; + break; + } + } + + Method finalTargetMethod = targetMethod; + return () -> + { + try + { + finalTargetMethod.setAccessible(true); + return (String) finalTargetMethod.invoke(null); + } + catch (Exception e) + { + throw new RuntimeException("Failed to invoke the lambda method.", e); + } + }; + } + catch (Throwable ex) + { + LangUtil.rethrowUnchecked(ex); + } + return null; + } + + private static InstanceIdSupplier defaultInstanceId( + Configuration config) { - return () -> - new BigInteger(130, new SecureRandom()).toString(Character.MAX_RADIX); + return () -> String.format("%s-%s", KAFKA_CLIENT_ID.get(config), UUID.randomUUID()); } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaBindingConfig.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaBindingConfig.java index df6aac76cc..52da2441c9 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaBindingConfig.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaBindingConfig.java @@ -19,6 +19,9 @@ import java.util.List; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaOptionsConfig; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaTopicConfig; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; @@ -45,7 +48,18 @@ public KafkaRouteConfig resolve( String topic) { return routes.stream() - .filter(r -> r.authorized(authorization) && r.matches(topic)) + .filter(r -> r.authorized(authorization) && r.matches(topic, null)) + .findFirst() + .orElse(null); + } + + public KafkaRouteConfig resolve( + long authorization, + String topic, + String groupId) + { + return routes.stream() + .filter(r -> r.authorized(authorization) && r.matches(topic, groupId)) .findFirst() .orElse(null); } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapter.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapter.java index 351d45ce06..c5d242261f 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapter.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaConditionConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; @@ -27,6 +28,7 @@ public final class KafkaConditionConfigAdapter implements ConditionConfigAdapterSpi, JsonbAdapter { private static final String TOPIC_NAME = "topic"; + private static final String GROUP_ID_NAME = "groupId"; @Override public String type() @@ -47,6 +49,11 @@ public JsonObject adaptToJson( object.add(TOPIC_NAME, kafkaCondition.topic); } + if (kafkaCondition.groupId != null) + { + object.add(GROUP_ID_NAME, kafkaCondition.groupId); + } + return object.build(); } @@ -58,6 +65,10 @@ public ConditionConfig adaptFromJson( ? object.getString(TOPIC_NAME) : null; - return new KafkaConditionConfig(topic); + String groupId = object.containsKey(GROUP_ID_NAME) + ? object.getString(GROUP_ID_NAME) + : null; + + return new KafkaConditionConfig(topic, groupId); } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionMatcher.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionMatcher.java index 37bf8d0e85..74802a51b6 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionMatcher.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionMatcher.java @@ -18,20 +18,25 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaConditionConfig; + public final class KafkaConditionMatcher { private final Matcher topicMatch; + private final Matcher grouoIdMatch; public KafkaConditionMatcher( KafkaConditionConfig condition) { this.topicMatch = condition.topic != null ? asMatcher(condition.topic) : null; + this.grouoIdMatch = condition.groupId != null ? asMatcher(condition.groupId) : null; } public boolean matches( - String topic) + String topic, + String groupId) { - return matchesTopic(topic); + return matchesTopic(topic) && matchesGroupId(groupId); } private boolean matchesTopic( @@ -40,9 +45,18 @@ private boolean matchesTopic( return this.topicMatch == null || this.topicMatch.reset(topic).matches(); } + private boolean matchesGroupId( + String groupId) + { + return this.grouoIdMatch == null || this.grouoIdMatch.reset(groupId).matches(); + } + private static Matcher asMatcher( String wildcard) { - return Pattern.compile(wildcard.replace(".", "\\.").replace("*", ".*")).matcher(""); + return Pattern.compile(wildcard + .replace(".", "\\.") + .replace("*", ".*")) + .matcher(""); } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapter.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapter.java index 8d5f24c8a2..7992783319 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapter.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapter.java @@ -26,6 +26,9 @@ import jakarta.json.JsonString; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaOptionsConfig; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaTopicConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaRouteConfig.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaRouteConfig.java index 8949acfc3c..30a21d5d03 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaRouteConfig.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaRouteConfig.java @@ -20,10 +20,10 @@ import java.util.List; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class KafkaRouteConfig extends OptionsConfig +public final class KafkaRouteConfig { public final long id; public final KafkaWithConfig with; @@ -50,8 +50,9 @@ boolean authorized( } boolean matches( - String topic) + String topic, + String groupId) { - return when.isEmpty() || when.stream().anyMatch(m -> m.matches(topic)); + return when.isEmpty() || when.stream().anyMatch(m -> m.matches(topic, groupId)); } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaScramMechanism.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaScramMechanism.java new file mode 100644 index 0000000000..05bd5fcb6d --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaScramMechanism.java @@ -0,0 +1,88 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.config; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public enum KafkaScramMechanism +{ + SCRAM_SHA_256("SHA-256", "HmacSHA256", 4096), + SCRAM_SHA_512("SHA-512", "HmacSHA512", 4096), + SCRAM_SHA_1("SHA-1", "HmacSHA1", 4096); + + private final String mechanismName; + private final String hashAlgorithm; + private final String macAlgorithm; + private final int minIterations; + + private static final Map MECHANISMS_MAP; + + static + { + Map map = new HashMap<>(); + for (KafkaScramMechanism mech : values()) + { + map.put(mech.mechanismName, mech); + } + MECHANISMS_MAP = Collections.unmodifiableMap(map); + } + + KafkaScramMechanism(String hashAlgorithm, String macAlgorithm, int minIterations) + { + this.mechanismName = "SCRAM-" + hashAlgorithm; + this.hashAlgorithm = hashAlgorithm; + this.macAlgorithm = macAlgorithm; + this.minIterations = minIterations; + } + + public final String mechanismName() + { + return mechanismName; + } + + public String hashAlgorithm() + { + return hashAlgorithm; + } + + public String macAlgorithm() + { + return macAlgorithm; + } + + public int minIterations() + { + return minIterations; + } + + public static KafkaScramMechanism forMechanismName(String mechanismName) + { + return MECHANISMS_MAP.get(mechanismName); + } + + public static Collection mechanismNames() + { + return MECHANISMS_MAP.keySet(); + } + + public static boolean isScram(String mechanismName) + { + return MECHANISMS_MAP.containsKey(mechanismName); + } +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaTopicConfigAdapter.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaTopicConfigAdapter.java index ffc1652e24..16ab5ff2f8 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaTopicConfigAdapter.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaTopicConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaTopicConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.types.KafkaDeltaType; import io.aklivity.zilla.runtime.binding.kafka.internal.types.KafkaOffsetType; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/ScramMechanism.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/ScramMechanism.java deleted file mode 100644 index d7cbe7fa05..0000000000 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/ScramMechanism.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.kafka.internal.config; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public enum ScramMechanism -{ - SCRAM_SHA_256("SHA-256", "HmacSHA256", 4096), - SCRAM_SHA_512("SHA-512", "HmacSHA512", 4096), - SCRAM_SHA_1("SHA-1", "HmacSHA1", 4096); - - private final String mechanismName; - private final String hashAlgorithm; - private final String macAlgorithm; - private final int minIterations; - - private static final Map MECHANISMS_MAP; - - static - { - Map map = new HashMap<>(); - for (ScramMechanism mech : values()) - { - map.put(mech.mechanismName, mech); - } - MECHANISMS_MAP = Collections.unmodifiableMap(map); - } - - ScramMechanism(String hashAlgorithm, String macAlgorithm, int minIterations) - { - this.mechanismName = "SCRAM-" + hashAlgorithm; - this.hashAlgorithm = hashAlgorithm; - this.macAlgorithm = macAlgorithm; - this.minIterations = minIterations; - } - - public final String mechanismName() - { - return mechanismName; - } - - public String hashAlgorithm() - { - return hashAlgorithm; - } - - public String macAlgorithm() - { - return macAlgorithm; - } - - public int minIterations() - { - return minIterations; - } - - public static ScramMechanism forMechanismName(String mechanismName) - { - return MECHANISMS_MAP.get(mechanismName); - } - - public static Collection mechanismNames() - { - return MECHANISMS_MAP.keySet(); - } - - public static boolean isScram(String mechanismName) - { - return MECHANISMS_MAP.containsKey(mechanismName); - } -} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientConsumerFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientConsumerFactory.java new file mode 100644 index 0000000000..4ade212901 --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientConsumerFactory.java @@ -0,0 +1,1044 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.LongFunction; +import java.util.function.LongSupplier; +import java.util.function.LongUnaryOperator; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.IntHashSet; +import org.agrona.collections.Object2ObjectHashMap; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Array32FW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaConsumerAssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaConsumerBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaConsumerDataExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaDataExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaTopicPartitionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; +import io.aklivity.zilla.runtime.engine.concurrent.Signaler; + +public final class KafkaCacheClientConsumerFactory implements BindingHandler +{ + private static final Consumer EMPTY_EXTENSION = ex -> {}; + + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final AbortFW abortRO = new AbortFW(); + private final ResetFW resetRO = new ResetFW(); + private final WindowFW windowRO = new WindowFW(); + private final ExtensionFW extensionRO = new ExtensionFW(); + private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); + private final KafkaDataExFW kafkaDataExRO = new KafkaDataExFW(); + private final KafkaResetExFW kafkaResetExRO = new KafkaResetExFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); + + private final int kafkaTypeId; + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final BufferPool bufferPool; + private final Signaler signaler; + private final BindingHandler streamFactory; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final LongSupplier supplyTraceId; + private final LongFunction supplyNamespace; + private final LongFunction supplyLocalName; + private final LongFunction supplyBinding; + + private final Object2ObjectHashMap clientConsumerFansByConsumer; + + public KafkaCacheClientConsumerFactory( + KafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding) + { + this.kafkaTypeId = context.supplyTypeId(KafkaBinding.NAME); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.bufferPool = context.bufferPool(); + this.signaler = context.signaler(); + this.streamFactory = context.streamFactory(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyTraceId = context::supplyTraceId; + this.supplyNamespace = context::supplyNamespace; + this.supplyLocalName = context::supplyLocalName; + this.supplyBinding = supplyBinding; + this.clientConsumerFansByConsumer = new Object2ObjectHashMap<>(); + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer sender) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert (initialId & 0x0000_0000_0000_0001L) != 0L; + + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extension.get(extensionRO::tryWrap); + assert beginEx != null && beginEx.typeId() == kafkaTypeId; + final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::wrap); + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_CONSUMER; + final KafkaConsumerBeginExFW kafkaConsumerBeginEx = kafkaBeginEx.consumer(); + final String groupId = kafkaConsumerBeginEx.groupId().asString(); + final String topic = kafkaConsumerBeginEx.topic().asString(); + final String consumerId = kafkaConsumerBeginEx.consumerId().asString(); + final int timeout = kafkaConsumerBeginEx.timeout(); + final IntHashSet partitions = new IntHashSet(); + kafkaConsumerBeginEx.partitionIds().forEach(p -> partitions.add(p.partitionId())); + + MessageConsumer newStream = null; + + final KafkaBindingConfig binding = supplyBinding.apply(routedId); + final KafkaRouteConfig resolved = binding != null ? binding.resolve(authorization, topic, groupId) : null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + + String fanKey = String.format("%s-%s-%s-%d", groupId, topic, consumerId, resolvedId); + KafkaCacheClientConsumerFan fan = clientConsumerFansByConsumer.get(fanKey); + + if (fan == null) + { + KafkaCacheClientConsumerFan newFan = + new KafkaCacheClientConsumerFan(routedId, resolvedId, authorization, fanKey, + groupId, topic, consumerId, partitions, timeout); + fan = newFan; + clientConsumerFansByConsumer.put(fanKey, fan); + } + + newStream = new KafkaCacheClientConsumerStream( + fan, + sender, + originId, + routedId, + initialId, + affinity, + authorization + )::onConsumerMessage; + } + + return newStream; + } + + private MessageConsumer newStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + final MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doDataNull( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + final class KafkaCacheClientConsumerFan + { + private final long originId; + private final long routedId; + private final long authorization; + private final String fanKey; + private final String groupId; + private final String topic; + private final String consumerId; + private final int timeout; + private final List members; + private final IntHashSet partitions; + private final IntHashSet assignedPartitions; + private final Object2ObjectHashMap assignments; + + private long initialId; + private long replyId; + private MessageConsumer receiver; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + + + private KafkaCacheClientConsumerFan( + long originId, + long routedId, + long authorization, + String fanKey, + String groupId, + String topic, + String consumerId, + IntHashSet partitions, + int timeout) + { + this.originId = originId; + this.routedId = routedId; + this.authorization = authorization; + this.groupId = groupId; + this.topic = topic; + this.consumerId = consumerId; + this.partitions = partitions; + this.timeout = timeout; + this.fanKey = fanKey; + this.members = new ArrayList<>(); + this.assignedPartitions = new IntHashSet(); + this.assignments = new Object2ObjectHashMap<>(); + } + + private void onConsumerFanMemberOpening( + long traceId, + KafkaCacheClientConsumerStream member) + { + members.add(member); + + assert !members.isEmpty(); + + doConsumerFanInitialBeginIfNecessary(traceId); + + if (KafkaState.initialOpened(state)) + { + member.doConsumerInitialWindow(traceId, 0L, 0, 0, 0); + } + + if (KafkaState.replyOpened(state)) + { + member.doConsumerReplyBeginIfNecessary(traceId); + } + } + + private void onConsumerFanMemberOpened( + long traceId, + KafkaCacheClientConsumerStream member) + { + if (!assignedPartitions.isEmpty()) + { + final KafkaDataExFW kafkaDataEx = + kafkaDataExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .consumer(m -> m + .partitions(p -> + assignedPartitions.forEach(ap -> p.item(np -> np.partitionId(ap)))) + .assignments(a -> + assignments.forEach((k, v) -> a.item(na -> na.consumerId(k) + .partitions(pa -> + v.forEach(pi -> pa.item(pai -> pai.partitionId(pi)))))))) + .build(); + member.doConsumerReplyDataIfNecessary(traceId, kafkaDataEx); + } + } + + private void onConsumerFanMemberClosed( + long traceId, + KafkaCacheClientConsumerStream member) + { + members.remove(member); + + if (members.isEmpty()) + { + cleanup(traceId); + } + } + + private void cleanup(long traceId) + { + doConsumerFanInitialEndIfNecessary(traceId); + doConsumerFanReplyResetIfNecessary(traceId); + } + + private void onConsumerFanClosed( + long traceId) + { + clientConsumerFansByConsumer.remove(this.fanKey); + cleanup(traceId); + } + + private void doConsumerFanInitialBeginIfNecessary( + long traceId) + { + if (KafkaState.closed(state)) + { + state = 0; + } + + if (!KafkaState.initialOpening(state)) + { + doConsumerFanInitialBegin(traceId); + } + } + + private void doConsumerFanInitialBegin( + long traceId) + { + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.receiver = newStream(this::onConsumerFanMessage, + originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, 0L, + ex -> ex.set((b, o, l) -> kafkaBeginExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .consumer(m -> m.groupId(groupId) + .consumerId(consumerId) + .timeout(timeout) + .topic(topic) + .partitionIds(p -> partitions.forEach(tp -> p.item(np -> np.partitionId(tp.intValue()))))) + .build() + .sizeof())); + state = KafkaState.openingInitial(state); + } + + private void doConsumerFanInitialEndIfNecessary( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doConsumerFanInitialEnd(traceId); + } + } + + private void doConsumerFanInitialEnd( + long traceId) + { + doEnd(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + + private void doConsumerFanInitialAbortIfNecessary( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doConsumerFanInitialAbort(traceId); + } + } + + private void doConsumerFanInitialAbort( + long traceId) + { + doAbort(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + + private void onConsumerFanInitialReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + final OctetsFW extension = reset.extension(); + + final KafkaResetExFW kafkaResetEx = extension.get(kafkaResetExRO::tryWrap); + final int error = kafkaResetEx != null ? kafkaResetEx.error() : -1; + + state = KafkaState.closedInitial(state); + + doConsumerFanReplyResetIfNecessary(traceId); + + members.forEach(s -> s.doConsumerInitialResetIfNecessary(traceId)); + + onConsumerFanClosed(traceId); + } + + private void onConsumerFanInitialWindow( + WindowFW window) + { + if (!KafkaState.initialOpened(state)) + { + + final long traceId = window.traceId(); + + state = KafkaState.openedInitial(state); + + members.forEach(s -> s.doConsumerInitialWindow(traceId, 0L, 0, 0, 0)); + } + } + + private void onConsumerFanMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onConsumerFanReplyBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onConsumerFanReplyData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onConsumerFanReplyEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onConsumerFanReplyAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onConsumerFanInitialReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onConsumerFanInitialWindow(window); + break; + default: + break; + } + } + + private void onConsumerFanReplyBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + state = KafkaState.openingReply(state); + + members.forEach(s -> s.doConsumerReplyBeginIfNecessary(traceId)); + + doConsumerFanReplyWindow(traceId, 0, bufferPool.slotCapacity()); + } + + private void onConsumerFanReplyData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final int reserved = data.reserved(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + assert replySeq <= replyAck + replyMax; + + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + assert kafkaDataEx == null || kafkaDataEx.kind() == KafkaBeginExFW.KIND_CONSUMER; + final KafkaConsumerDataExFW kafkaConsumerDataEx = kafkaDataEx != null ? kafkaDataEx.consumer() : null; + + if (kafkaConsumerDataEx != null) + { + final Array32FW newPartitions = kafkaConsumerDataEx.partitions(); + final Array32FW newAssignments = kafkaConsumerDataEx.assignments(); + + assignedPartitions.clear(); + newPartitions.forEach(p -> this.assignedPartitions.add(p.partitionId())); + + assignments.clear(); + newAssignments.forEach(a -> + { + IntHashSet partitions = new IntHashSet(); + a.partitions().forEach(p -> partitions.add(p.partitionId())); + assignments.put(a.consumerId().asString(), partitions); + }); + + members.forEach(s -> s.doConsumerReplyDataIfNecessary(traceId, kafkaDataEx)); + } + + doConsumerFanReplyWindow(traceId, 0, replyMax); + } + + private void onConsumerFanReplyEnd( + EndFW end) + { + final long traceId = end.traceId(); + + state = KafkaState.closedReply(state); + + doConsumerFanInitialEndIfNecessary(traceId); + + members.forEach(s -> s.doConsumerReplyEndIfNecessary(traceId)); + + onConsumerFanClosed(traceId); + } + + private void onConsumerFanReplyAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedReply(state); + + doConsumerFanInitialAbortIfNecessary(traceId); + + members.forEach(s -> s.doConsumerReplyAbortIfNecessary(traceId)); + + onConsumerFanClosed(traceId); + } + + private void doConsumerFanReplyResetIfNecessary( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doConsumerFanReplyReset(traceId); + } + } + + private void doConsumerFanReplyReset( + long traceId) + { + doReset(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization); + + state = KafkaState.closedReply(state); + } + + private void doConsumerFanReplyWindow( + long traceId, + int minReplyNoAck, + int minReplyMax) + { + final long newReplyAck = Math.max(replySeq - minReplyNoAck, replyAck); + + if (newReplyAck > replyAck || minReplyMax > replyMax || !KafkaState.replyOpened(state)) + { + replyAck = newReplyAck; + assert replyAck <= replySeq; + + replyMax = minReplyMax; + + state = KafkaState.openedReply(state); + + doWindow(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, 0L, 0); + } + } + } + + private final class KafkaCacheClientConsumerStream + { + private final KafkaCacheClientConsumerFan fan; + private final MessageConsumer sender; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final long affinity; + private final long authorization; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private long replyBudgetId; + + KafkaCacheClientConsumerStream( + KafkaCacheClientConsumerFan fan, + MessageConsumer sender, + long originId, + long routedId, + long initialId, + long affinity, + long authorization) + { + this.fan = fan; + this.sender = sender; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.affinity = affinity; + this.authorization = authorization; + } + + private void onConsumerMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onConsumerInitialBegin(begin); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onConsumerInitialEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onConsumerInitialAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onConsumerReplyWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onConsumerReplyReset(reset); + break; + default: + break; + } + } + + private void onConsumerInitialBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + state = KafkaState.openingInitial(state); + + fan.onConsumerFanMemberOpening(traceId, this); + } + + private void onConsumerInitialEnd( + EndFW end) + { + final long traceId = end.traceId(); + + state = KafkaState.closedInitial(state); + + fan.onConsumerFanMemberClosed(traceId, this); + + doConsumerReplyEndIfNecessary(traceId); + } + + private void onConsumerInitialAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedInitial(state); + + fan.onConsumerFanMemberClosed(traceId, this); + + doConsumerReplyAbortIfNecessary(traceId); + } + + private void doConsumerInitialResetIfNecessary( + long traceId) + { + if (KafkaState.initialOpening(state) && !KafkaState.initialClosed(state)) + { + doConsumerInitialReset(traceId); + } + + state = KafkaState.closedInitial(state); + } + + private void doConsumerInitialReset( + long traceId) + { + state = KafkaState.closedInitial(state); + + doReset(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization); + } + + private void doConsumerInitialWindow( + long traceId, + long budgetId, + int minInitialNoAck, + int minInitialPad, + int minInitialMax) + { + final long newInitialAck = Math.max(initialSeq - minInitialNoAck, initialAck); + + if (newInitialAck > initialAck || minInitialMax > initialMax || !KafkaState.initialOpened(state)) + { + initialAck = newInitialAck; + assert initialAck <= initialSeq; + + initialMax = minInitialMax; + + state = KafkaState.openedInitial(state); + + doWindow(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, minInitialPad); + } + } + + private void doConsumerReplyBeginIfNecessary( + long traceId) + { + if (!KafkaState.replyOpening(state)) + { + doConsumerReplyBegin(traceId); + } + } + + private void doConsumerReplyBegin( + long traceId) + { + state = KafkaState.openingReply(state); + + doBegin(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, EMPTY_EXTENSION); + } + + private void doConsumerReplyDataIfNecessary( + long traceId, + Flyweight extension) + { + if (KafkaState.replyOpened(state)) + { + doConsumerReplyData(traceId, extension); + } + } + + private void doConsumerReplyData( + long traceId, + Flyweight extension) + { + final int reserved = replyPad; + + doDataNull(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, reserved, extension); + + replySeq += reserved; + } + + private void doConsumerReplyEndIfNecessary( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doConsumerReplyEnd(traceId); + } + + state = KafkaState.closedReply(state); + } + + private void doConsumerReplyEnd( + long traceId) + { + state = KafkaState.closedReply(state); + doEnd(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + private void doConsumerReplyAbortIfNecessary( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doConsumerReplyAbort(traceId); + } + + state = KafkaState.closedReply(state); + } + + private void doConsumerReplyAbort( + long traceId) + { + state = KafkaState.closedReply(state); + doAbort(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + private void onConsumerReplyReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + fan.onConsumerFanMemberClosed(traceId, this); + + doConsumerInitialResetIfNecessary(traceId); + } + + private void onConsumerReplyWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + this.replyAck = acknowledge; + this.replyMax = maximum; + this.replyPad = padding; + this.replyBudgetId = budgetId; + + assert replyAck <= replySeq; + + if (!KafkaState.replyOpened(state)) + { + state = KafkaState.openedReply(state); + + final long traceId = window.traceId(); + fan.onConsumerFanMemberOpened(traceId, this); + } + } + } +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFactory.java index 8833175c5e..adc07c8e6e 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFactory.java @@ -64,6 +64,14 @@ public KafkaCacheClientFactory( final KafkaCacheClientDescribeFactory cacheDescribeFactory = new KafkaCacheClientDescribeFactory( config, context, bindings::get, supplyCacheRoute); + final KafkaCacheGroupFactory cacheGroupFactory = new KafkaCacheGroupFactory(config, context, bindings::get); + + final KafkaCacheClientConsumerFactory consumerGroupFactory = + new KafkaCacheClientConsumerFactory(config, context, bindings::get); + + final KafkaCacheOffsetFetchFactory cacheOffsetFetchFactory = + new KafkaCacheOffsetFetchFactory(config, context, bindings::get); + final KafkaCacheClientFetchFactory cacheFetchFactory = new KafkaCacheClientFetchFactory( config, context, bindings::get, accountant::supplyDebitor, supplyCache, supplyCacheRoute); @@ -76,6 +84,9 @@ public KafkaCacheClientFactory( final Int2ObjectHashMap factories = new Int2ObjectHashMap<>(); factories.put(KafkaBeginExFW.KIND_META, cacheMetaFactory); factories.put(KafkaBeginExFW.KIND_DESCRIBE, cacheDescribeFactory); + factories.put(KafkaBeginExFW.KIND_GROUP, cacheGroupFactory); + factories.put(KafkaBeginExFW.KIND_CONSUMER, consumerGroupFactory); + factories.put(KafkaBeginExFW.KIND_OFFSET_FETCH, cacheOffsetFetchFactory); factories.put(KafkaBeginExFW.KIND_FETCH, cacheFetchFactory); factories.put(KafkaBeginExFW.KIND_PRODUCE, cacheProduceFactory); factories.put(KafkaBeginExFW.KIND_MERGED, cacheMergedFactory); diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFetchFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFetchFactory.java index c9bb19d703..0bc5c7b6b9 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFetchFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientFetchFactory.java @@ -899,8 +899,8 @@ private final class KafkaCacheClientFetchStream private int state; private int flushFramesSent; - private long replyDebitorIndex = NO_DEBITOR_INDEX; - private BudgetDebitor replyDebitor; + private long replyDebIndex = NO_DEBITOR_INDEX; + private BudgetDebitor replyDeb; private long initialSeq; private long initialAck; @@ -912,7 +912,7 @@ private final class KafkaCacheClientFetchStream private int replyMax; private int replyMin; - private long replyBudgetId; + private long replyBud; private long initialOffset; private int messageOffset; @@ -1159,7 +1159,7 @@ private void doClientReplyDataIfNecessary( { assert !KafkaState.closing(state) : String.format("!replyClosing(%08x) [%016x] [%016x] [%016x] %s", - state, replyBudgetId, replyId, replyDebitorIndex, replyDebitor); + state, replyBud, replyId, replyDebIndex, replyDeb); final long initialIsolatedOffset = initialGroupIsolatedOffset.getAsLong(); @@ -1275,11 +1275,11 @@ private void doClientReplyData( { int reserved = reservedMax; boolean claimed = false; - if (replyDebitorIndex != NO_DEBITOR_INDEX) + if (replyDebIndex != NO_DEBITOR_INDEX) { final int lengthMax = Math.min(reservedMax - replyPad, remaining); final int deferredMax = remaining - lengthMax; - reserved = replyDebitor.claim(traceId, replyDebitorIndex, replyId, reservedMin, reservedMax, deferredMax); + reserved = replyDeb.claim(traceId, replyDebIndex, replyId, reservedMin, reservedMax, deferredMax); claimed = reserved > 0; } @@ -1375,7 +1375,7 @@ private void doClientReplyDataFull( long latestOffset) { doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, flags, replyBudgetId, reserved, value, + traceId, authorization, flags, replyBud, reserved, value, ex -> ex.set((b, o, l) -> kafkaDataExRW.wrap(b, o, l) .typeId(kafkaTypeId) .fetch(f -> f.timestamp(timestamp) @@ -1420,7 +1420,7 @@ private void doClientReplyDataInit( long latestOffset) { doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, flags, replyBudgetId, reserved, fragment, + traceId, authorization, flags, replyBud, reserved, fragment, ex -> ex.set((b, o, l) -> kafkaDataExRW.wrap(b, o, l) .typeId(kafkaTypeId) .fetch(f -> f.deferred(deferred) @@ -1451,7 +1451,7 @@ private void doClientReplyDataNone( int flags) { doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, flags, replyBudgetId, reserved, fragment, EMPTY_EXTENSION); + traceId, authorization, flags, replyBud, reserved, fragment, EMPTY_EXTENSION); replySeq += reserved; @@ -1473,7 +1473,7 @@ private void doClientReplyDataFin( long latestOffset) { doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, flags, replyBudgetId, reserved, fragment, + traceId, authorization, flags, replyBud, reserved, fragment, ex -> ex.set((b, o, l) -> kafkaDataExRW.wrap(b, o, l) .typeId(kafkaTypeId) .fetch(f -> f.partition(p -> p.partitionId(partitionId) @@ -1512,7 +1512,7 @@ private void doClientReplyFlush( assert partitionOffset >= cursor.offset : String.format("%d >= %d", partitionOffset, cursor.offset); doFlush(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, replyBudgetId, reserved, ex -> ex + traceId, authorization, replyBud, reserved, ex -> ex .set((b, o, l) -> kafkaFlushExRW.wrap(b, o, l) .typeId(kafkaTypeId) .fetch(f -> f @@ -1546,7 +1546,7 @@ private void doClientReplyFlush( //assert partitionOffset >= cursor.offset : String.format("%d >= %d", partitionOffset, cursor.offset); doFlush(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, replyBudgetId, reserved, ex -> ex + traceId, authorization, replyBud, reserved, ex -> ex .set((b, o, l) -> kafkaFlushExRW.wrap(b, o, l) .typeId(kafkaTypeId) .fetch(f -> f @@ -1622,8 +1622,8 @@ private void onClientReplyWindow( final int padding = window.padding(); final int minimum = window.minimum(); - assert replyBudgetId == 0L || replyBudgetId == budgetId : - String.format("%d == 0 || %d == %d)", replyBudgetId, replyBudgetId, budgetId); + assert replyBud == 0L || replyBud == budgetId : + String.format("%d == 0 || %d == %d)", replyBud, replyBud, budgetId); assert acknowledge <= sequence; assert sequence <= replySeq; @@ -1634,17 +1634,17 @@ private void onClientReplyWindow( this.replyMax = maximum; this.replyPad = padding; this.replyMin = minimum; - this.replyBudgetId = budgetId; + this.replyBud = budgetId; if (!KafkaState.replyOpened(state)) { state = KafkaState.openedReply(state); - if (replyBudgetId != NO_BUDGET_ID && replyDebitorIndex == NO_DEBITOR_INDEX) + if (replyBud != NO_BUDGET_ID && replyDebIndex == NO_DEBITOR_INDEX) { - replyDebitor = supplyDebitor.apply(replyBudgetId); - replyDebitorIndex = replyDebitor.acquire(replyBudgetId, replyId, this::doClientReplyDataIfNecessary); - assert replyDebitorIndex != NO_DEBITOR_INDEX; + replyDeb = supplyDebitor.apply(replyBud); + replyDebIndex = replyDeb.acquire(replyBud, replyId, this::doClientReplyDataIfNecessary); + assert replyDebIndex != NO_DEBITOR_INDEX; } } @@ -1670,10 +1670,10 @@ private void onClientReplyReset( private void cleanupDebitorIfNecessary() { - if (replyDebitor != null && replyDebitorIndex != NO_DEBITOR_INDEX) + if (replyDeb != null && replyDebIndex != NO_DEBITOR_INDEX) { - replyDebitor.release(replyBudgetId, replyId); - replyDebitorIndex = NO_DEBITOR_INDEX; + replyDeb.release(replyBud, replyId); + replyDebIndex = NO_DEBITOR_INDEX; } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheGroupFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheGroupFactory.java new file mode 100644 index 0000000000..43dbddc16a --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheGroupFactory.java @@ -0,0 +1,1064 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import java.util.function.Consumer; +import java.util.function.LongFunction; +import java.util.function.LongUnaryOperator; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; + +public final class KafkaCacheGroupFactory implements BindingHandler +{ + private static final Consumer EMPTY_EXTENSION = ex -> {}; + + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final FlushFW flushRO = new FlushFW(); + private final AbortFW abortRO = new AbortFW(); + private final ResetFW resetRO = new ResetFW(); + private final WindowFW windowRO = new WindowFW(); + private final ExtensionFW extensionRO = new ExtensionFW(); + private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + + private final int kafkaTypeId; + private final MutableDirectBuffer writeBuffer; + private final BufferPool bufferPool; + private final BindingHandler streamFactory; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final LongFunction supplyBinding; + + public KafkaCacheGroupFactory( + KafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding) + { + this.kafkaTypeId = context.supplyTypeId(KafkaBinding.NAME); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.bufferPool = context.bufferPool(); + this.streamFactory = context.streamFactory(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyBinding = supplyBinding; + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer sender) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert (initialId & 0x0000_0000_0000_0001L) != 0L; + + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extension.get(extensionRO::tryWrap); + assert beginEx != null && beginEx.typeId() == kafkaTypeId; + final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::tryWrap); + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_GROUP; + final KafkaGroupBeginExFW kafkaGroupBeginEx = kafkaBeginEx.group(); + final String groupId = kafkaGroupBeginEx.groupId().asString(); + final String protocol = kafkaGroupBeginEx.protocol().asString(); + final int timeout = kafkaGroupBeginEx.timeout(); + + MessageConsumer newStream = null; + + final KafkaBindingConfig binding = supplyBinding.apply(routedId); + final KafkaRouteConfig resolved = binding != null ? binding.resolve(authorization, null, groupId) : null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + + newStream = new KafkaCacheGroupApp( + sender, + originId, + routedId, + initialId, + affinity, + authorization, + resolvedId, + groupId, + protocol, + timeout)::onGroupMessage; + } + + return newStream; + } + + private MessageConsumer newStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + OctetsFW extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + final MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + OctetsFW payload, + Flyweight extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + OctetsFW extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + final class KafkaCacheGroupNet + { + private final long originId; + private final long routedId; + private final long authorization; + private final KafkaCacheGroupApp delegate; + + private long initialId; + private long replyId; + private MessageConsumer receiver; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + private long initialBud; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaCacheGroupNet( + KafkaCacheGroupApp delegate, + long originId, + long routedId, + long authorization) + { + this.delegate = delegate; + this.originId = originId; + this.routedId = routedId; + this.receiver = MessageConsumer.NOOP; + this.authorization = authorization; + } + + private void doGroupInitialBegin( + long traceId, + OctetsFW extension) + { + if (KafkaState.closed(state)) + { + state = 0; + } + + if (!KafkaState.initialOpening(state)) + { + if (KafkaConfiguration.DEBUG) + { + System.out.format("%s GroupId connect\n", delegate.groupId); + } + + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.receiver = newStream(this::onGroupMessage, + originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, 0L, extension); + state = KafkaState.openingInitial(state); + } + } + + private void doGroupInitialData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doGroupInitialFlush( + long traceId, + OctetsFW extension) + { + doFlush(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, initialBud, 0, extension); + } + + private void doGroupInitialEnd( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doEnd(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void doGroupInitialAbort( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doAbort(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void onGroupInitialReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + + delegate.initialAck = acknowledge; + state = KafkaState.closedInitial(state); + + assert delegate.initialAck <= delegate.initialSeq; + + delegate.doGroupInitialReset(traceId); + + doGroupReplyReset(traceId); + } + + + private void onGroupInitialWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + initialBud = budgetId; + state = KafkaState.openedInitial(state); + + assert initialAck <= initialSeq; + + delegate.doGroupInitialWindow(authorization, traceId, budgetId, padding); + } + + private void onGroupMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onGroupReplyBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onGroupReplyData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onGroupReplyFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onGroupReplyEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onGroupReplyAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onGroupInitialReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onGroupInitialWindow(window); + break; + default: + break; + } + } + + private void onGroupReplyBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + state = KafkaState.openingReply(state); + + delegate.doGroupReplyBegin(traceId, begin.extension()); + } + + private void onGroupReplyData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final int flags = data.flags(); + final int reserved = data.reserved(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + assert replySeq <= replyAck + replyMax; + + delegate.doGroupReplyData(traceId, flags, reserved, payload, extension); + } + + private void onGroupReplyFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final int reserved = flush.reserved(); + final OctetsFW extension = flush.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + assert replySeq <= replyAck + replyMax; + + delegate.doGroupReplyFlush(traceId, extension); + } + + private void onGroupReplyEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + delegate.doGroupReplyEnd(traceId); + } + + private void onGroupReplyAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + delegate.doGroupReplyAbort(traceId); + } + + private void doGroupReplyReset( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doReset(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization); + + state = KafkaState.closedReply(state); + } + } + + private void doGroupReplyWindow( + long traceId, + long authorization, + long budgetId, + int padding) + { + replyAck = Math.max(delegate.replyAck - replyPad, 0); + replyMax = delegate.replyMax; + + doWindow(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding + replyPad); + } + } + + private final class KafkaCacheGroupApp + { + private final KafkaCacheGroupNet group; + private final MessageConsumer sender; + private final String groupId; + private final String protocol; + private final int timeout; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final long affinity; + private final long authorization; + + private int state; + + private long replyBudgetId; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + private long replyBud; + private int replyCap; + + KafkaCacheGroupApp( + MessageConsumer sender, + long originId, + long routedId, + long initialId, + long affinity, + long authorization, + long resolvedId, + String groupId, + String protocol, + int timeout) + { + this.group = new KafkaCacheGroupNet(this, routedId, resolvedId, authorization); + this.sender = sender; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.affinity = affinity; + this.authorization = authorization; + this.groupId = groupId; + this.protocol = protocol; + this.timeout = timeout; + } + + private void onGroupMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onGroupInitialBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onGroupInitialData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onGroupInitialEnd(end); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onGroupInitialFlush(flush); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onGroupInitialAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onGroupReplyWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onGroupReplyReset(reset); + break; + default: + break; + } + } + + private void onGroupInitialBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + final OctetsFW extension = begin.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + state = KafkaState.openingInitial(state); + + assert initialAck <= initialSeq; + + group.doGroupInitialBegin(traceId, extension); + } + + private void onGroupInitialData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + final int flags = data.flags(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + group.doGroupInitialData(traceId, authorization, budgetId, reserved, flags, payload, extension); + } + + private void onGroupInitialEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + + group.doGroupInitialEnd(traceId); + } + + private void onGroupInitialFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final OctetsFW extension = flush.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + + group.doGroupInitialFlush(traceId, extension); + } + + private void onGroupInitialAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + + group.doGroupInitialAbort(traceId); + } + + private void doGroupInitialReset( + long traceId) + { + if (KafkaState.initialOpening(state) && !KafkaState.initialClosed(state)) + { + state = KafkaState.closedInitial(state); + + doReset(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization); + } + + state = KafkaState.closedInitial(state); + } + + private void doGroupInitialWindow( + long authorization, + long traceId, + long budgetId, + int padding) + { + initialAck = group.initialAck; + initialMax = group.initialMax; + + doWindow(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, padding); + } + + private void doGroupReplyBegin( + long traceId, + OctetsFW extension) + { + state = KafkaState.openingReply(state); + + doBegin(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, extension); + } + + private void doGroupReplyData( + long traceId, + int flag, + int reserved, + OctetsFW payload, + Flyweight extension) + { + + doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, flag, reserved, payload, extension); + + replySeq += reserved; + } + + private void doGroupReplyFlush( + long traceId, + OctetsFW extension) + { + doFlush(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, 0, extension); + } + + private void doGroupReplyEnd( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doEnd(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + state = KafkaState.closedReply(state); + } + + private void doGroupReplyAbort( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doAbort(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + state = KafkaState.closedReply(state); + } + + private void onGroupReplyReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final int maximum = reset.maximum(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + cleanup(traceId); + } + + private void onGroupReplyWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyBud = budgetId; + replyPad = padding; + replyCap = capabilities; + state = KafkaState.openedReply(state); + + assert replyAck <= replySeq; + + group.doGroupReplyWindow(traceId, acknowledge, budgetId, padding); + } + + private void cleanup( + long traceId) + { + doGroupInitialReset(traceId); + doGroupReplyAbort(traceId); + + group.doGroupInitialAbort(traceId); + group.doGroupReplyReset(traceId); + } + } +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheOffsetFetchFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheOffsetFetchFactory.java new file mode 100644 index 0000000000..625dd927dd --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheOffsetFetchFactory.java @@ -0,0 +1,1046 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import java.util.function.Consumer; +import java.util.function.LongFunction; +import java.util.function.LongUnaryOperator; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaOffsetFetchBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; + + +public final class KafkaCacheOffsetFetchFactory implements BindingHandler +{ + private static final Consumer EMPTY_EXTENSION = ex -> {}; + + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final FlushFW flushRO = new FlushFW(); + private final AbortFW abortRO = new AbortFW(); + private final ResetFW resetRO = new ResetFW(); + private final WindowFW windowRO = new WindowFW(); + private final ExtensionFW extensionRO = new ExtensionFW(); + private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + + private final int kafkaTypeId; + private final MutableDirectBuffer writeBuffer; + private final BufferPool bufferPool; + private final BindingHandler streamFactory; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final LongFunction supplyBinding; + + public KafkaCacheOffsetFetchFactory( + KafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding) + { + this.kafkaTypeId = context.supplyTypeId(KafkaBinding.NAME); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.bufferPool = context.bufferPool(); + this.streamFactory = context.streamFactory(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyBinding = supplyBinding; + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer sender) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert (initialId & 0x0000_0000_0000_0001L) != 0L; + + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extension.get(extensionRO::tryWrap); + assert beginEx != null && beginEx.typeId() == kafkaTypeId; + final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::tryWrap); + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_OFFSET_FETCH; + final KafkaOffsetFetchBeginExFW kafkaOffsetFetchBeginEx = kafkaBeginEx.offsetFetch(); + final String groupId = kafkaOffsetFetchBeginEx.groupId().asString(); + + MessageConsumer newStream = null; + + final KafkaBindingConfig binding = supplyBinding.apply(routedId); + final KafkaRouteConfig resolved = binding != null ? binding.resolve(authorization, null, groupId) : null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + + newStream = new KafkaCacheOffsetFetchApp( + sender, + originId, + routedId, + initialId, + affinity, + authorization, + resolvedId)::onOffsetFetchMessage; + } + + return newStream; + } + + private MessageConsumer newStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + OctetsFW extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + final MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + OctetsFW payload, + Flyweight extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + + + private void doDataNull( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Consumer extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + final class KafkaCacheOffsetFetchNet + { + private final long originId; + private final long routedId; + private final long authorization; + private final KafkaCacheOffsetFetchApp delegate; + + private long initialId; + private long replyId; + private MessageConsumer receiver; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + private long initialBud; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaCacheOffsetFetchNet( + KafkaCacheOffsetFetchApp delegate, + long originId, + long routedId, + long authorization) + { + this.delegate = delegate; + this.originId = originId; + this.routedId = routedId; + this.receiver = MessageConsumer.NOOP; + this.authorization = authorization; + } + + private void doOffsetFetchInitialBegin( + long traceId, + long affinity, + OctetsFW extension) + { + if (KafkaState.closed(state)) + { + state = 0; + } + + if (!KafkaState.initialOpening(state)) + { + + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.receiver = newStream(this::onOffsetFetchMessage, + originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, this.authorization, affinity, extension); + state = KafkaState.openingInitial(state); + } + } + + private void doOffsetFetchInitialData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doOffsetFetchInitialFlush( + long traceId) + { + doFlush(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, initialBud, 0, EMPTY_EXTENSION); + } + + private void doOffsetFetchInitialEnd( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doEnd(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void doOffsetFetchInitialAbort( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doAbort(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void onOffsetFetchInitialReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + + delegate.initialAck = acknowledge; + state = KafkaState.closedInitial(state); + + assert delegate.initialAck <= delegate.initialSeq; + + delegate.doOffsetFetchInitialReset(traceId); + + doOffsetFetchReplyReset(traceId); + } + + + private void onOffsetFetchInitialWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + initialBud = budgetId; + state = KafkaState.openedInitial(state); + + assert initialAck <= initialSeq; + + delegate.doOffsetFetchInitialWindow(authorization, traceId, budgetId, padding); + } + + private void onOffsetFetchMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onOffsetFetchReplyBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onOffsetFetchReplyData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onOffsetFetchReplyEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onOffsetFetchReplyAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onOffsetFetchInitialReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onOffsetFetchInitialWindow(window); + break; + default: + break; + } + } + + private void onOffsetFetchReplyBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + state = KafkaState.openingReply(state); + + delegate.doOffsetFetchReplyBegin(traceId, begin.extension()); + } + + private void onOffsetFetchReplyData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final int flags = data.flags(); + final int reserved = data.reserved(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + assert replySeq <= replyAck + replyMax; + + delegate.doOffsetFetchReplyData(traceId, flags, reserved, payload, extension); + } + + private void onOffsetFetchReplyEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + delegate.doOffsetFetchReplyEnd(traceId); + } + + private void onOffsetFetchReplyAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + delegate.doOffsetFetchReplyAbort(traceId); + } + + private void doOffsetFetchReplyReset( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doReset(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization); + + state = KafkaState.closedReply(state); + } + } + + private void doOffsetFetchReplyWindow( + long traceId, + long authorization, + long budgetId, + int padding) + { + replyAck = Math.max(delegate.replyAck - replyPad, 0); + replyMax = delegate.replyMax; + + doWindow(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding + replyPad); + } + } + + private final class KafkaCacheOffsetFetchApp + { + private final KafkaCacheOffsetFetchNet offsetFetch; + private final MessageConsumer sender; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final long affinity; + private final long authorization; + + private int state; + + private long replyBudgetId; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + private long replyBud; + private int replyCap; + + KafkaCacheOffsetFetchApp( + MessageConsumer sender, + long originId, + long routedId, + long initialId, + long affinity, + long authorization, + long resolvedId) + { + this.offsetFetch = new KafkaCacheOffsetFetchNet(this, routedId, resolvedId, authorization); + this.sender = sender; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.affinity = affinity; + this.authorization = authorization; + } + + private void onOffsetFetchMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onOffsetFetchInitialBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onOffsetFetchInitialData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onOffsetFetchInitialEnd(end); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onOffsetFetchInitialFlush(flush); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onOffsetFetchInitialAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onOffsetFetchReplyWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onOffsetFetchReplyReset(reset); + break; + default: + break; + } + } + + private void onOffsetFetchInitialBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + final OctetsFW extension = begin.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + state = KafkaState.openingInitial(state); + + assert initialAck <= initialSeq; + + offsetFetch.doOffsetFetchInitialBegin(traceId, affinity, extension); + } + + private void onOffsetFetchInitialData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + final int flags = data.flags(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + offsetFetch.doOffsetFetchInitialData(traceId, authorization, budgetId, reserved, flags, payload, extension); + } + + private void onOffsetFetchInitialEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + + offsetFetch.doOffsetFetchInitialEnd(traceId); + } + + private void onOffsetFetchInitialFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + + offsetFetch.doOffsetFetchInitialFlush(traceId); + } + + private void onOffsetFetchInitialAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + + offsetFetch.doOffsetFetchInitialAbort(traceId); + } + + private void doOffsetFetchInitialReset( + long traceId) + { + if (KafkaState.initialOpening(state) && !KafkaState.initialClosed(state)) + { + state = KafkaState.closedInitial(state); + + doReset(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization); + } + + state = KafkaState.closedInitial(state); + } + + private void doOffsetFetchInitialWindow( + long authorization, + long traceId, + long budgetId, + int padding) + { + initialAck = offsetFetch.initialAck; + initialMax = offsetFetch.initialMax; + + doWindow(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, padding); + } + + private void doOffsetFetchReplyBegin( + long traceId, + OctetsFW extension) + { + state = KafkaState.openingReply(state); + + doBegin(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, extension); + } + + private void doOffsetFetchReplyData( + long traceId, + int flag, + int reserved, + OctetsFW payload, + Flyweight extension) + { + + doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, flag, reserved, payload, extension); + + replySeq += reserved; + } + + private void doOffsetFetchReplyEnd( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doEnd(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + state = KafkaState.closedReply(state); + } + + private void doOffsetFetchReplyAbort( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doAbort(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + state = KafkaState.closedReply(state); + } + + private void onOffsetFetchReplyReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final int maximum = reset.maximum(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + cleanup(traceId); + } + + private void onOffsetFetchReplyWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyBud = budgetId; + replyPad = padding; + replyCap = capabilities; + state = KafkaState.openedReply(state); + + assert replyAck <= replySeq; + + offsetFetch.doOffsetFetchReplyWindow(traceId, acknowledge, budgetId, padding); + } + + private void cleanup( + long traceId) + { + doOffsetFetchInitialReset(traceId); + doOffsetFetchReplyAbort(traceId); + + offsetFetch.doOffsetFetchInitialAbort(traceId); + offsetFetch.doOffsetFetchReplyReset(traceId); + } + } +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerBootstrapFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerBootstrapFactory.java index 3354dde69a..44f10a622d 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerBootstrapFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerBootstrapFactory.java @@ -27,10 +27,10 @@ import org.agrona.collections.MutableInteger; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaTopicConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaTopicConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.types.ArrayFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.KafkaConfigFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.KafkaOffsetFW; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerConsumerFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerConsumerFactory.java new file mode 100644 index 0000000000..01541a6904 --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerConsumerFactory.java @@ -0,0 +1,1454 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.LongFunction; +import java.util.function.LongUnaryOperator; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.IntHashSet; +import org.agrona.collections.Object2ObjectHashMap; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Array32FW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.rebalance.MemberAssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.rebalance.TopicAssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaConsumerBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaDataExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaFlushExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupFlushExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupMemberFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupMemberMetadataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupTopicMetadataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; + +public final class KafkaCacheServerConsumerFactory implements BindingHandler +{ + private static final Consumer EMPTY_EXTENSION = ex -> {}; + private static final DirectBuffer EMPTY_BUFFER = new UnsafeBuffer(); + private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(EMPTY_BUFFER, 0, 0); + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final FlushFW flushRO = new FlushFW(); + private final AbortFW abortRO = new AbortFW(); + private final ResetFW resetRO = new ResetFW(); + private final WindowFW windowRO = new WindowFW(); + private final ExtensionFW extensionRO = new ExtensionFW(); + private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); + private final KafkaFlushExFW kafkaFlushExRO = new KafkaFlushExFW(); + private final KafkaGroupMemberMetadataFW kafkaGroupMemberMetadataRO = new KafkaGroupMemberMetadataFW(); + private final Array32FW groupTopicsMetadataRO = + new Array32FW<>(new KafkaGroupTopicMetadataFW()); + private final Array32FW topicAssignmentsRO = + new Array32FW<>(new TopicAssignmentFW()); + + private final Array32FW.Builder memberAssignmentRW = + new Array32FW.Builder<>(new MemberAssignmentFW.Builder(), new MemberAssignmentFW()); + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); + private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); + private final KafkaGroupMemberMetadataFW.Builder kafkaGroupMemberMetadataRW = new KafkaGroupMemberMetadataFW.Builder(); + + private final int kafkaTypeId; + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final BufferPool bufferPool; + private final BindingHandler streamFactory; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final LongFunction supplyBinding; + private final Object2ObjectHashMap clientConsumerFansByGroupId; + + public KafkaCacheServerConsumerFactory( + KafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding) + { + this.kafkaTypeId = context.supplyTypeId(KafkaBinding.NAME); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.bufferPool = context.bufferPool(); + this.streamFactory = context.streamFactory(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyBinding = supplyBinding; + this.clientConsumerFansByGroupId = new Object2ObjectHashMap<>(); + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer sender) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert (initialId & 0x0000_0000_0000_0001L) != 0L; + + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extension.get(extensionRO::tryWrap); + assert beginEx != null && beginEx.typeId() == kafkaTypeId; + final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::tryWrap); + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_CONSUMER; + final KafkaConsumerBeginExFW kafkaConsumerBeginEx = kafkaBeginEx.consumer(); + final String groupId = kafkaConsumerBeginEx.groupId().asString(); + final String topic = kafkaConsumerBeginEx.topic().asString(); + String consumerId = kafkaConsumerBeginEx.consumerId().asString(); + consumerId = consumerId != null ? consumerId : ""; + final int timeout = kafkaConsumerBeginEx.timeout(); + final List partitions = new ArrayList<>(); + kafkaConsumerBeginEx.partitionIds().forEach(p -> partitions.add(p.partitionId())); + + MessageConsumer newStream = null; + + final KafkaBindingConfig binding = supplyBinding.apply(routedId); + final KafkaRouteConfig resolved = binding != null ? binding.resolve(authorization, topic, groupId) : null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + + KafkaCacheServerConsumerFanout fanout = clientConsumerFansByGroupId.get(groupId); + + if (fanout == null) + { + KafkaCacheServerConsumerFanout newFanout = + new KafkaCacheServerConsumerFanout(routedId, resolvedId, authorization, consumerId, groupId, timeout); + fanout = newFanout; + clientConsumerFansByGroupId.put(groupId, fanout); + } + + newStream = new KafkaCacheServerConsumerStream( + fanout, + sender, + originId, + routedId, + initialId, + affinity, + authorization, + topic, + partitions)::onConsumerMessage; + } + + return newStream; + } + + private MessageConsumer newStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + final MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + DirectBuffer buffer, + int offset, + int limit, + Flyweight extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(buffer, offset, limit) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + OctetsFW payload, + Consumer extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload) + .extension(extension) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + + private void doDataNull( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Consumer extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + final class KafkaCacheServerConsumerFanout + { + private final String consumerId; + private final String groupId; + private final long originId; + private final long routedId; + private final long authorization; + private final List streams; + private final Object2ObjectHashMap members; + private final Object2ObjectHashMap partitionsByTopic; + private final Object2ObjectHashMap> consumers; + private final Object2ObjectHashMap assignments; + + private long initialId; + private long replyId; + private MessageConsumer receiver; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + private long initialBud; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + private String leaderId; + private String memberId; + private int timeout; + + + private KafkaCacheServerConsumerFanout( + long originId, + long routedId, + long authorization, + String consumerId, + String groupId, + int timeout) + { + this.originId = originId; + this.routedId = routedId; + this.authorization = authorization; + this.consumerId = consumerId; + this.groupId = groupId; + this.timeout = timeout; + this.streams = new ArrayList<>(); + this.members = new Object2ObjectHashMap<>(); + this.partitionsByTopic = new Object2ObjectHashMap<>(); + this.consumers = new Object2ObjectHashMap<>(); + this.assignments = new Object2ObjectHashMap<>(); + } + + private void onConsumerFanoutStreamOpening( + long traceId, + KafkaCacheServerConsumerStream stream) + { + streams.add(stream); + + assert !streams.isEmpty(); + + doConsumerInitialBegin(traceId, stream); + + if (KafkaState.initialOpened(state)) + { + stream.doConsumerInitialWindow(authorization, traceId, initialBud, 0); + } + + if (KafkaState.replyOpened(state)) + { + stream.doConsumerReplyBegin(traceId); + } + } + + private void onConsumerFanoutMemberOpened( + long traceId, + KafkaCacheServerConsumerStream stream) + { + final TopicConsumer topicConsumer = assignments.get(stream.topic); + if (topicConsumer != null) + { + stream.doConsumerReplyData(traceId, 3, replyPad, EMPTY_OCTETS, + ex -> ex.set((b, o, l) -> kafkaDataExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .consumer(c -> c.partitions(p -> topicConsumer + .partitions.forEach(np -> p.item(tp -> tp.partitionId(np)))) + .assignments(a -> topicConsumer.consumers.forEach(u -> + a.item(ua -> ua.consumerId(u.consumerId).partitions(p -> u.partitions + .forEach(np -> + p.item(tp -> tp.partitionId(np)))))))) + .build() + .sizeof())); + } + } + + private void doConsumerInitialBegin( + long traceId, + KafkaCacheServerConsumerStream stream) + { + if (KafkaState.closed(state)) + { + state = 0; + } + + if (!KafkaState.initialOpening(state)) + { + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + KafkaGroupMemberMetadataFW metadata = kafkaGroupMemberMetadataRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .consumerId(consumerId) + .topics(t -> streams.forEach(s -> t.item(tp -> tp + .topic(s.topic) + .partitions(p -> s.partitions.forEach(sp -> + p.item(gtp -> gtp.partitionId(sp))))))) + .build(); + + this.receiver = newStream(this::onConsumerMessage, + originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, 0L, + ex -> ex.set((b, o, l) -> kafkaBeginExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .group(g -> + g.groupId(groupId) + .protocol("highlander") + .timeout(timeout) + .metadataLen(metadata.sizeof()) + .metadata(metadata.buffer(), 0, metadata.sizeof())) + .build().sizeof())); + state = KafkaState.openingInitial(state); + } + else if (!assignments.containsKey(stream.topic)) + { + doConsumerInitialFlush(traceId, + ex -> ex.set((b, o, l) -> kafkaFlushExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .group(g -> g.leaderId(leaderId) + .memberId(memberId) + .members(gm -> + { + KafkaGroupMemberMetadataFW metadata = kafkaGroupMemberMetadataRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .consumerId(consumerId) + .topics(t -> streams.forEach(s -> t.item(tp -> tp + .topic(s.topic) + .partitions(p -> s.partitions.forEach(sp -> + p.item(gtp -> gtp.partitionId(sp))))))) + .build(); + + gm.item(i -> + { + KafkaGroupMemberFW.Builder builder = i.id(memberId); + builder.metadataLen(metadata.sizeof()) + .metadata(metadata.buffer(), 0, metadata.sizeof()); + }); + })) + .build() + .sizeof())); + } + } + + private void doConsumerInitialData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + DirectBuffer buffer, + int offset, + int limit, + Flyweight extension) + { + doData(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, buffer, offset, limit, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doConsumerInitialFlush( + long traceId, + Consumer extension) + { + doFlush(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, initialBud, 0, extension); + } + + private void doConsumerInitialEnd( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doEnd(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void doConsumerInitialAbort( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doAbort(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void onConsumerInitialReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= this.initialAck; + + this.initialAck = acknowledge; + state = KafkaState.closedInitial(state); + + assert this.initialAck <= this.initialSeq; + + streams.forEach(m -> m.cleanup(traceId)); + + doConsumerReplyReset(traceId); + + onConsumerFanClosed(traceId); + } + + + private void onConsumerInitialWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert acknowledge >= this.initialAck; + assert maximum >= this.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + initialBud = budgetId; + state = KafkaState.openedInitial(state); + + assert initialAck <= initialSeq; + + streams.forEach(m -> m.doConsumerInitialWindow(authorization, traceId, budgetId, padding)); + } + + private void onConsumerMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onConsumerReplyBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onConsumerReplyData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onConsumerReplyFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onConsumerReplyEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onConsumerReplyAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onConsumerInitialReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onConsumerInitialWindow(window); + break; + default: + break; + } + } + + private void onConsumerReplyBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + state = KafkaState.openedReply(state); + + streams.forEach(m -> m.doConsumerReplyBegin(traceId)); + } + + private void onConsumerReplyFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorizationId = flush.authorization(); + final int reserved = flush.reserved(); + final OctetsFW extension = flush.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + replyAck = replySeq; + + assert replyAck <= replySeq; + assert replySeq <= replyAck + replyMax; + + final KafkaFlushExFW flushEx = extension.get(kafkaFlushExRO::tryWrap); + + if (flushEx != null) + { + KafkaGroupFlushExFW kafkaGroupFlushEx = flushEx.group(); + + leaderId = kafkaGroupFlushEx.leaderId().asString(); + memberId = kafkaGroupFlushEx.memberId().asString(); + + partitionsByTopic.clear(); + members.clear(); + + kafkaGroupFlushEx.members().forEach(m -> + { + final OctetsFW metadata = m.metadata(); + final KafkaGroupMemberMetadataFW groupMetadata = kafkaGroupMemberMetadataRO + .wrap(metadata.buffer(), metadata.offset(), metadata.limit()); + final String consumerId = kafkaGroupMemberMetadataRO.consumerId().asString(); + + final String mId = m.id().asString(); + members.put(mId, consumerId); + + groupMetadata.topics().forEach(mt -> + { + final String topic = mt.topic().asString(); + IntHashSet partitions = partitionsByTopic.computeIfAbsent(topic, s -> new IntHashSet()); + mt.partitions().forEach(p -> partitions.add(p.partitionId())); + }); + }); + } + + doPartitionAssignment(traceId, authorization); + } + + private void onConsumerReplyData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorizationId = data.authorization(); + final int flags = data.flags(); + final int reserved = data.reserved(); + final OctetsFW payload = data.payload(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + assert replySeq <= replyAck + replyMax; + + Array32FW topicAssignments = topicAssignmentsRO + .wrap(payload.buffer(), payload.offset(), payload.limit()); + + this.assignments.clear(); + + topicAssignments.forEach(ta -> + { + KafkaCacheServerConsumerStream stream = + streams.stream().filter(s -> s.topic.equals(ta.topic().asString())).findFirst().get(); + IntHashSet partitions = new IntHashSet(); + List topicConsumers = new ArrayList<>(); + + stream.doConsumerReplyData(traceId, flags, replyPad, EMPTY_OCTETS, + ex -> ex.set((b, o, l) -> kafkaDataExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .consumer(c -> c.partitions(p -> ta + .partitions() + .forEach(np -> + { + partitions.add(np.partitionId()); + p.item(tp -> tp.partitionId(np.partitionId())); + })) + .assignments(a -> ta.userdata().forEach(u -> + { + final IntHashSet consumerTopicPartitions = new IntHashSet(); + a.item(ua -> ua.consumerId(u.consumerId()).partitions(p -> u.partitions() + .forEach(np -> + { + consumerTopicPartitions.add(np.partitionId()); + p.item(tp -> tp.partitionId(np.partitionId())); + }))); + topicConsumers.add(new TopicPartition(u.consumerId().asString(), ta.topic().asString(), + consumerTopicPartitions)); + }))) + .build() + .sizeof())); + + assignments.put(ta.topic().asString(), new TopicConsumer(partitions, topicConsumers)); + }); + } + + private void onConsumerReplyEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + streams.forEach(s -> s.doConsumerReplyEnd(traceId)); + doConsumerInitialEnd(traceId); + + onConsumerFanClosed(traceId); + } + + private void onConsumerReplyAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + streams.forEach(s -> s.cleanup(traceId)); + + doConsumerInitialAbort(traceId); + + onConsumerFanClosed(traceId); + } + + private void doConsumerReplyReset( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doReset(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization); + + state = KafkaState.closedReply(state); + } + } + + private void doConsumerReplyWindow( + long traceId, + long authorization, + long budgetId, + int padding) + { + replyAck = Math.max(replyAck - replyPad, 0); + + doWindow(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding + replyPad); + } + + private void doPartitionAssignment( + long traceId, + long authorization) + { + if (memberId.equals(leaderId)) + { + int memberSize = members.size(); + consumers.clear(); + + partitionsByTopic.forEach((t, p) -> + { + final int partitionSize = p.size(); + final int numberOfPartitionsPerMember = partitionSize / memberSize; + final int extraPartition = partitionSize % memberSize; + + int partitionIndex = 0; + int newPartitionPerTopic = numberOfPartitionsPerMember + extraPartition; + + IntHashSet.IntIterator iterator = p.iterator(); + + for (String member : members.keySet()) + { + String consumerId = members.get(member); + List topicPartitions = consumers.computeIfAbsent( + member, tp -> new ArrayList<>()); + IntHashSet partitions = new IntHashSet(); + + for (; partitionIndex < newPartitionPerTopic; partitionIndex++) + { + final int partitionId = iterator.nextValue(); + partitions.add(partitionId); + } + topicPartitions.add(new TopicPartition(consumerId, t, partitions)); + + newPartitionPerTopic += numberOfPartitionsPerMember; + } + }); + } + + doMemberAssigment(traceId, authorization); + } + + private void doMemberAssigment( + long traceId, + long authorization) + { + if (!consumers.isEmpty()) + { + Array32FW.Builder assignmentBuilder = memberAssignmentRW + .wrap(writeBuffer, DataFW.FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()); + + this.consumers.forEach((k, v) -> + { + assignmentBuilder.item(ma -> ma + .memberId(k) + .assignments(ta -> v.forEach(tp -> ta.item(i -> i + .topic(tp.topic) + .partitions(p -> tp.partitions.forEach(t -> p.item(tpa -> tpa.partitionId(t)))) + .userdata(u -> + this.consumers.forEach((ak, av) -> av + .stream().filter(atp -> atp.topic.equals(tp.topic)).forEach(at -> + u.item(ud -> ud + .consumerId(at.consumerId) + .partitions(pt -> at.partitions.forEach(up -> + pt.item(pi -> pi.partitionId(up)))))))) + )))); + }); + + Array32FW assignment = assignmentBuilder.build(); + + doConsumerInitialData(traceId, authorization, initialBud, assignment.sizeof(), 3, + assignment.buffer(), assignment.offset(), assignment.sizeof(), EMPTY_OCTETS); + } + else + { + doConsumerInitialData(traceId, authorization, initialBud, memberAssignmentRW.sizeof(), 3, + EMPTY_OCTETS.buffer(), EMPTY_OCTETS.offset(), EMPTY_OCTETS.sizeof(), EMPTY_OCTETS); + } + } + + private void onConsumerFanClosed( + long traceId) + { + clientConsumerFansByGroupId.remove(this.groupId); + } + } + + final class KafkaCacheServerConsumerStream + { + private final KafkaCacheServerConsumerFanout fanout; + private final MessageConsumer sender; + private final String topic; + private final List partitions; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final long affinity; + private final long authorization; + + private int state; + + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + private long replyBud; + private int replyCap; + + KafkaCacheServerConsumerStream( + KafkaCacheServerConsumerFanout fanout, + MessageConsumer sender, + long originId, + long routedId, + long initialId, + long affinity, + long authorization, + String topic, + List partitions) + { + this.fanout = fanout; + this.sender = sender; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.affinity = affinity; + this.authorization = authorization; + this.topic = topic; + this.partitions = partitions; + } + + private void onConsumerMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onConsumerInitialBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onConsumerInitialData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onConsumerInitialFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onConsumerInitialEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onConsumerInitialAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onConsumerReplyWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onConsumerReplyReset(reset); + break; + default: + break; + } + } + + private void onConsumerInitialBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + state = KafkaState.openingInitial(state); + + assert initialAck <= initialSeq; + + fanout.onConsumerFanoutStreamOpening(traceId, this); + } + + private void onConsumerInitialData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + final int flags = data.flags(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + } + + private void onConsumerInitialEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + } + + private void onConsumerInitialFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + } + + private void onConsumerInitialAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = KafkaState.closedInitial(state); + + assert initialAck <= initialSeq; + + doConsumerReplyAbort(traceId); + fanout.streams.remove(this); + } + + private void doConsumerInitialReset( + long traceId) + { + if (KafkaState.initialOpening(state) && !KafkaState.initialClosed(state)) + { + state = KafkaState.closedInitial(state); + + doReset(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization); + } + + state = KafkaState.closedInitial(state); + } + + private void doConsumerInitialWindow( + long authorization, + long traceId, + long budgetId, + int padding) + { + doWindow(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, padding); + } + + private void doConsumerReplyBegin( + long traceId) + { + state = KafkaState.openingReply(state); + + doBegin(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, EMPTY_OCTETS); + } + + private void doConsumerReplyData( + long traceId, + int flag, + int reserved, + OctetsFW payload, + Consumer extension) + { + doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBud, flag, reserved, payload, extension); + + replySeq += reserved; + } + + private void doConsumerReplyEnd( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doEnd(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + state = KafkaState.closedReply(state); + } + + private void doConsumerReplyAbort( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doAbort(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_EXTENSION); + } + + state = KafkaState.closedReply(state); + } + + private void onConsumerReplyReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final int maximum = reset.maximum(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + cleanup(traceId); + } + + private void onConsumerReplyWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorizationId = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyBud = budgetId; + replyPad = padding; + replyCap = capabilities; + + assert replyAck <= replySeq; + + fanout.replyMax = replyMax; + fanout.doConsumerReplyWindow(traceId, authorizationId, budgetId, padding); + + if (!KafkaState.replyOpened(state)) + { + state = KafkaState.openedReply(state); + + fanout.onConsumerFanoutMemberOpened(traceId, this); + } + } + + private void cleanup( + long traceId) + { + doConsumerInitialReset(traceId); + doConsumerReplyAbort(traceId); + } + } + + final class TopicPartition + { + private final String consumerId; + private final String topic; + private final IntHashSet partitions; + + TopicPartition( + String consumerId, + String topic, + IntHashSet partitions) + { + this.consumerId = consumerId; + this.topic = topic; + this.partitions = partitions; + } + } + + final class TopicConsumer + { + private final IntHashSet partitions; + private final List consumers; + + TopicConsumer( + IntHashSet partitions, + List consumers) + { + this.partitions = partitions; + this.consumers = consumers; + } + } +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFactory.java index f9950aabb7..1d28951bc4 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFactory.java @@ -67,6 +67,14 @@ public KafkaCacheServerFactory( final KafkaCacheServerDescribeFactory cacheDescribeFactory = new KafkaCacheServerDescribeFactory( config, context, bindings::get, supplyCache, supplyCacheRoute); + final KafkaCacheGroupFactory cacheGroupFactory = new KafkaCacheGroupFactory(config, context, bindings::get); + + final KafkaCacheServerConsumerFactory consumerGroupFactory = + new KafkaCacheServerConsumerFactory(config, context, bindings::get); + + final KafkaCacheOffsetFetchFactory cacheOffsetFetchFactory = + new KafkaCacheOffsetFetchFactory(config, context, bindings::get); + final KafkaCacheServerFetchFactory cacheFetchFactory = new KafkaCacheServerFetchFactory( config, context, bindings::get, supplyCache, supplyCacheRoute); @@ -76,6 +84,9 @@ public KafkaCacheServerFactory( factories.put(KafkaBeginExFW.KIND_BOOTSTRAP, cacheBootstrapFactory); factories.put(KafkaBeginExFW.KIND_META, cacheMetaFactory); factories.put(KafkaBeginExFW.KIND_DESCRIBE, cacheDescribeFactory); + factories.put(KafkaBeginExFW.KIND_GROUP, cacheGroupFactory); + factories.put(KafkaBeginExFW.KIND_CONSUMER, consumerGroupFactory); + factories.put(KafkaBeginExFW.KIND_OFFSET_FETCH, cacheOffsetFetchFactory); factories.put(KafkaBeginExFW.KIND_FETCH, cacheFetchFactory); factories.put(KafkaBeginExFW.KIND_PRODUCE, cacheProduceFactory); diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFetchFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFetchFactory.java index 2a3109db76..9792ab6228 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFetchFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheServerFetchFactory.java @@ -42,6 +42,7 @@ import org.agrona.collections.Int2IntHashMap; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaTopicConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; import io.aklivity.zilla.runtime.binding.kafka.internal.cache.KafkaCache; @@ -52,7 +53,6 @@ import io.aklivity.zilla.runtime.binding.kafka.internal.cache.KafkaCacheTopic; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaTopicConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.ArrayFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientConnectionPool.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientConnectionPool.java new file mode 100644 index 0000000000..c1eb7f2c27 --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientConnectionPool.java @@ -0,0 +1,1347 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.binding.kafka.internal.types.ProxyAddressProtocol.STREAM; +import static io.aklivity.zilla.runtime.engine.budget.BudgetCreditor.NO_BUDGET_ID; +import static io.aklivity.zilla.runtime.engine.budget.BudgetCreditor.NO_CREDITOR_INDEX; +import static io.aklivity.zilla.runtime.engine.concurrent.Signaler.NO_CANCEL_ID; +import static java.lang.System.currentTimeMillis; + +import java.util.function.Consumer; +import java.util.function.IntConsumer; +import java.util.function.LongSupplier; +import java.util.function.LongUnaryOperator; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.Long2LongHashMap; +import org.agrona.collections.Long2ObjectHashMap; +import org.agrona.collections.LongArrayQueue; +import org.agrona.collections.Object2ObjectHashMap; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; +import io.aklivity.zilla.runtime.binding.kafka.internal.budget.MergedBudgetCreditor; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.ProxyAddressInetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.RequestHeaderFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.ResponseHeaderFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ProxyBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.SignalFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.concurrent.Signaler; + +public final class KafkaClientConnectionPool +{ + private static final long NO_DELTA = -1L; + private static final int KAFKA_FRAME_LENGTH_FIELD_OFFSET = 4; + private static final int FLAG_FIN = 0x01; + private static final int FLAG_INIT = 0x02; + private static final int FLAG_SKIP = 0x08; + private static final int FLAG_NONE = 0x00; + private static final Consumer EMPTY_EXTENSION = ex -> {}; + + private static final int SIGNAL_CONNECTION_CLEANUP = 0x80000001; + private static final int SIGNAL_STREAM_INITIAL_RESET = 0x80000001; + private static final int SIGNAL_STREAM_REPLY_BEGIN = 0x80000002; + private static final int SIGNAL_STREAM_REPLY_END = 0x80000003; + private static final int SIGNAL_STREAM_REPLY_ABORT = 0x80000004; + private static final String CLUSTER = ""; + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final AbortFW abortRO = new AbortFW(); + private final SignalFW signalRO = new SignalFW(); + private final ResetFW resetRO = new ResetFW(); + private final WindowFW windowRO = new WindowFW(); + private final ProxyBeginExFW proxyBeginExRO = new ProxyBeginExFW(); + private final ResponseHeaderFW responseHeaderRO = new ResponseHeaderFW(); + + private final ProxyBeginExFW.Builder proxyBeginExRW = new ProxyBeginExFW.Builder(); + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final SignalFW.Builder signalRW = new SignalFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + + private final RequestHeaderFW.Builder requestHeaderRW = new RequestHeaderFW.Builder(); + + private final RequestHeaderFW requestHeaderRO = new RequestHeaderFW(); + + private final MergedBudgetCreditor creditor; + private final int proxyTypeId; + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer encodeBuffer; + private final KafkaClientSignaler signaler; + private final BindingHandler streamFactory; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final LongSupplier supplyTraceId; + private final Object2ObjectHashMap connectionPool; + private final Long2ObjectHashMap streamsByInitialIds; + + public KafkaClientConnectionPool( + KafkaConfiguration config, + EngineContext context, + MergedBudgetCreditor creditor) + { + this.proxyTypeId = context.supplyTypeId("proxy"); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.encodeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.signaler = new KafkaClientSignaler(context.signaler()); + this.streamFactory = context.streamFactory(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyTraceId = context::supplyTraceId; + this.creditor = creditor; + this.connectionPool = new Object2ObjectHashMap(); + this.streamsByInitialIds = new Long2ObjectHashMap<>(); + } + + private MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer sender) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + + assert (initialId & 0x0000_0000_0000_0001L) != 0L; + + final OctetsFW extension = begin.extension(); + final ProxyBeginExFW proxyBeginEx = extension.get(proxyBeginExRO::tryWrap); + + MessageConsumer newStream = null; + String address = CLUSTER; + + if (proxyBeginEx != null) + { + final ProxyAddressInetFW inet = proxyBeginEx.address().inet(); + String host = inet.destination().asString(); + int port = inet.destinationPort(); + address = String.format("%s:%d", host, port); + } + + final KafkaClientConnection connection = connectionPool.computeIfAbsent(address, s -> + newConnection(originId, routedId, authorization)); + newStream = connection.newStream(msgTypeId, buffer, index, length, sender); + + return newStream; + } + + private KafkaClientConnection newConnection( + long originId, + long routedId, + long authorization) + { + return new KafkaClientConnection(originId, routedId, authorization); + } + + private MessageConsumer newNetworkStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + final MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + int flags, + long budgetId, + int reserved, + OctetsFW payload, + Flyweight extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + int flags, + long budgetId, + int reserved, + DirectBuffer payload, + int offset, + int length, + Flyweight extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload, offset, length) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doSignal( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + int signalId) + { + final SignalFW signal = signalRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(0) + .traceId(traceId) + .cancelId(0) + .signalId(signalId) + .contextId(0) + .build(); + + receiver.accept(signal.typeId(), signal.buffer(), signal.offset(), signal.sizeof()); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + public BindingHandler streamFactory() + { + return this::newStream; + } + + public class KafkaClientSignaler implements Signaler + { + private final Signaler delegate; + + public KafkaClientSignaler( + Signaler delegate) + { + + this.delegate = delegate; + } + + @Override + public long signalAt( + long timeMillis, + int signalId, + IntConsumer handler) + { + return delegate.signalAt(timeMillis, signalId, handler); + } + + @Override + public void signalNow( + long originId, + long routedId, + long streamId, + int signalId, + int contextId) + { + assert contextId == 0; + + KafkaClientStream stream = streamsByInitialIds.get(streamId); + stream.doStreamSignalNow(signalId); + } + + @Override + public long signalAt( + long timeMillis, + long originId, + long routedId, + long streamId, + int signalId, + int contextId) + { + assert contextId == 0; + + KafkaClientStream stream = streamsByInitialIds.get(streamId); + return stream.doStreamSignalAt(timeMillis, signalId); + } + + @Override + public long signalTask( + Runnable task, + long originId, + long routedId, + long streamId, + int signalId, + int contextId) + { + return 0; + } + + @Override + public boolean cancel( + long cancelId) + { + return delegate.cancel(cancelId); + } + } + + public Signaler signaler() + { + return signaler; + } + + final class KafkaClientStream + { + private final KafkaClientConnection connection; + private final long originId; + private final long routedId; + private final long authorization; + private final MessageConsumer sender; + + private final long initialId; + private final long replyId; + private long initialSeq; + private long initialAck; + private int initialMax; + private int initialPad; + private long initialBud; + private long initialSeqDelta = NO_DELTA; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + private long replyBud; + + private int nextRequestId; + private int nexResponseId; + private int requestBytes; + private int responseBytes; + + private int state; + + + private KafkaClientStream( + KafkaClientConnection connection, + MessageConsumer sender, + long originId, + long routedId, + long initialId, + long authorization) + { + this.connection = connection; + this.sender = sender; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.authorization = authorization; + } + + private void onStreamMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onStreamBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onStreamData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onStreamEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onStreamAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onStreamWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onStreamReset(reset); + break; + default: + break; + } + } + + private void onStreamBegin( + BeginFW begin) + { + final long initialId = begin.streamId(); + final long traceId = begin.traceId(); + + assert (initialId & 0x0000_0000_0000_0001L) != 0L; + + final OctetsFW extension = begin.extension(); + final ProxyBeginExFW proxyBeginEx = extension.get(proxyBeginExRO::tryWrap); + + state = KafkaState.openingInitial(state); + + String host = null; + int port = 0; + + if (proxyBeginEx != null) + { + final ProxyAddressInetFW inet = proxyBeginEx.address().inet(); + host = inet.destination().asString(); + port = inet.destinationPort(); + } + + connection.doConnectionBegin(traceId, host, port); + + connection.doConnectionSignalNow(initialId, SIGNAL_STREAM_REPLY_BEGIN); + } + + private void onStreamData( + DataFW data) + { + final long initialId = data.streamId(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + final int flags = data.flags(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + initialSeqDelta = connection.initialSeq; + + if (requestBytes == 0) + { + nextRequestId++; + + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + + RequestHeaderFW requestHeader = requestHeaderRO.wrap(buffer, offset, limit); + requestBytes = requestHeader.length() + KAFKA_FRAME_LENGTH_FIELD_OFFSET; + } + + requestBytes -= payload.sizeof(); + connection.doConnectionData(initialId, traceId, authorization, budgetId, + flags, reserved, payload, extension); + assert requestBytes >= 0; + } + + private void onStreamEnd( + EndFW end) + { + state = KafkaState.closedInitial(state); + + connection.doConnectionSignalNow(initialId, SIGNAL_STREAM_REPLY_END); + } + + private void onStreamAbort( + AbortFW abort) + { + state = KafkaState.closedInitial(state); + + connection.doConnectionSignalNow(initialId, SIGNAL_STREAM_REPLY_ABORT); + } + + private void onStreamReset( + ResetFW reset) + { + state = KafkaState.closingReply(state); + + connection.doConnectionSignalNow(initialId, SIGNAL_STREAM_INITIAL_RESET); + } + + private void onStreamWindow( + WindowFW window) + { + final long acknowledge = window.acknowledge(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int replyMax = window.maximum(); + + assert replyAck <= replySeq; + + state = KafkaState.openedReply(state); + + connection.doConnectionWindow(traceId, acknowledge, budgetId, padding, replyMax); + } + + private void doStreamWindow( + long authorization, + long traceId, + long budgetId, + int padding) + { + initialSeq = connection.initialSeq - initialSeqDelta; + initialAck = connection.initialAck - initialSeqDelta; + initialMax = connection.initialMax; + + doWindow(sender, originId, routedId, initialId, 0, 0, initialMax, + traceId, authorization, budgetId, padding); + } + + private void doStreamBegin( + long traceId) + { + state = KafkaState.openingReply(state); + + doBegin(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, initialBud, EMPTY_EXTENSION); + + doStreamWindow(connection.authorization, traceId, connection.connectionInitialBudgetId, + connection.initialPad); + } + + private void doStreamData( + long traceId, + int flags, + long sequence, + long acknowledge, + int reserved, + DirectBuffer payload, + int offset, + int length, + Flyweight extension) + { + replySeq = sequence; + replyAck = acknowledge; + + if (responseBytes == 0) + { + nexResponseId++; + final ResponseHeaderFW responseHeader = responseHeaderRO.wrap(payload, offset, offset + length); + responseBytes = responseHeader.length() + KAFKA_FRAME_LENGTH_FIELD_OFFSET; + } + + responseBytes -= length; + + if (!KafkaState.replyClosing(state)) + { + doData(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, flags, replyBud, reserved, payload, offset, length, extension); + } + else + { + if (responseBytes == 0) + { + doStreamEnd(traceId); + } + } + } + + private void doStreamEnd( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + state = KafkaState.closingReply(state); + if (nextRequestId == nexResponseId) + { + state = KafkaState.closedReply(state); + + doEnd(sender, originId, routedId, replyId, 0, 0, 0, + traceId, authorization, EMPTY_EXTENSION); + + streamsByInitialIds.remove(initialId); + } + } + } + + private void doStreamAbort( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + state = KafkaState.closingReply(state); + + if (nextRequestId == nexResponseId) + { + state = KafkaState.closedReply(state); + + doAbort(sender, originId, routedId, replyId, 0, 0, 0, + traceId, authorization, EMPTY_EXTENSION); + + streamsByInitialIds.remove(initialId); + } + } + } + + private void doStreamReset( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + state = KafkaState.closedInitial(state); + + doReset(sender, originId, routedId, initialId, 0, 0, 0, + traceId, authorization); + + streamsByInitialIds.remove(initialId); + } + } + + private void cleanupStream( + long traceId) + { + doStreamReset(traceId); + doStreamAbort(traceId); + + streamsByInitialIds.remove(initialId); + } + + private void doStreamSignalNow( + int signalId) + { + connection.doConnectionSignalNow(initialId, signalId); + } + + private long doStreamSignalAt( + long timeMillis, + int signalId) + { + return connection.doConnectionSignalAt(initialId, timeMillis, signalId); + } + + private void onSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final int signalId = signal.signalId(); + + switch (signalId) + { + case SIGNAL_STREAM_REPLY_BEGIN: + doStreamBegin(traceId); + break; + case SIGNAL_STREAM_REPLY_END: + doStreamEnd(traceId); + break; + case SIGNAL_STREAM_REPLY_ABORT: + doStreamAbort(traceId); + break; + case SIGNAL_STREAM_INITIAL_RESET: + doStreamReset(traceId); + break; + default: + doSignal(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, signalId); + } + } + } + + final class KafkaClientConnection implements BindingHandler + { + private final long originId; + private final long routedId; + private final long authorization; + private final LongArrayQueue correlations; + private final Long2LongHashMap signalerCorrelations; + + private long initialId; + private long replyId; + private MessageConsumer receiver; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + private int initialMin; + private int initialPad; + private long initialBud; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private int nextRequestId; + private int nextContextId; + private long connectionInitialBudgetId = NO_BUDGET_ID; + private long reconnectAt = NO_CANCEL_ID; + private int requestBytes; + private int responseBytes; + + private KafkaClientConnection( + long originId, + long routedId, + long authorization) + { + this.originId = originId; + this.routedId = routedId; + this.authorization = authorization; + this.correlations = new LongArrayQueue(); + this.signalerCorrelations = new Long2LongHashMap(-1L); + } + + private void doConnectionBegin( + long traceId, + String host, + int port) + { + if (KafkaState.closed(state)) + { + state = 0; + } + + if (!KafkaState.initialOpening(state)) + { + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + Consumer extension = EMPTY_EXTENSION; + + state = KafkaState.openingInitial(state); + + if (host != null) + { + extension = e -> e.set((b, o, l) -> proxyBeginExRW.wrap(b, o, l) + .typeId(proxyTypeId) + .address(a -> a.inet(i -> i.protocol(p -> p.set(STREAM)) + .source("0.0.0.0") + .destination(host) + .sourcePort(0) + .destinationPort(port))) + .build() + .sizeof()); + } + + this.receiver = newNetworkStream(this::onConnectionMessage, + originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, 0L, extension); + } + } + + private void doConnectionData( + long connectionInitialId, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + OctetsFW payload, + Flyweight extension) + { + if (requestBytes == 0) + { + final int requestId = nextRequestId++; + correlations.add(connectionInitialId); + + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + + RequestHeaderFW requestHeader = requestHeaderRO.wrap(buffer, offset, limit); + requestBytes = requestHeader.length() + KAFKA_FRAME_LENGTH_FIELD_OFFSET; + + int progress = 0; + RequestHeaderFW newRequestHeader = requestHeaderRW.wrap(encodeBuffer, 0, encodeBuffer.capacity()) + .length(requestHeader.length()) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId()) + .build(); + progress = newRequestHeader.limit(); + + final int remaining = payload.sizeof() - progress; + encodeBuffer.putBytes(progress, buffer, requestHeader.limit(), remaining); + + final int length = progress + remaining; + doData(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, flags, budgetId, reserved, encodeBuffer, 0, length, extension); + + requestBytes -= length; + assert requestBytes >= 0; + } + else + { + doData(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, flags, budgetId, reserved, payload, extension); + requestBytes -= payload.sizeof(); + } + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doConnectionEnd( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doEnd(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void doConnectionAbort( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doAbort(receiver, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + + state = KafkaState.closedInitial(state); + } + } + + private void doConnectionSignalNow( + long streamId, + int signalId) + { + nextContextId++; + signalerCorrelations.put(nextContextId, streamId); + signaler.delegate.signalNow(originId, routedId, this.initialId, signalId, nextContextId); + } + + private long doConnectionSignalAt( + long streamId, + long timeMillis, + int signalId) + { + nextContextId++; + signalerCorrelations.put(nextContextId, streamId); + return signaler.delegate.signalAt( + timeMillis, originId, routedId, this.initialId, signalId, nextContextId); + } + + private void doConnectionReset( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doReset(receiver, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization); + + state = KafkaState.closedReply(state); + } + } + + private void doConnectionWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int replyMax) + { + replyAck = Math.max(replyAck - replyPad, 0); + this.replyMax = replyMax; + + doWindow(receiver, originId, routedId, replyId, replySeq, replyAck, this.replyMax, + traceId, authorization, budgetId, padding + replyPad); + } + + private void onConnectionMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onConnectionBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onConnectionData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onConnectionEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onConnectionAbort(abort); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onConnectionSignal(signal); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onConnectionReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onConnectionWindow(window); + break; + default: + break; + } + } + + private void onConnectionBegin( + BeginFW begin) + { + final long authorization = begin.authorization(); + final long traceId = begin.traceId(); + + state = KafkaState.openingReply(state); + + doConnectionWindow(traceId, authorization, 0, replyPad, replyMax); + } + + private void onConnectionData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final int flags = data.flags(); + final int reserved = data.reserved(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + assert replySeq <= replyAck + replyMax; + + final DirectBuffer buffer = payload.buffer(); + final int limit = payload.limit(); + int progress = payload.offset(); + + while (progress < limit) + { + final int beforeResponseBytes = responseBytes; + if (responseBytes == 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.wrap(buffer, progress, limit); + responseBytes = responseHeader.length() + KAFKA_FRAME_LENGTH_FIELD_OFFSET; + } + + final int responseBytesMin = Math.min(responseBytes, payload.sizeof()); + responseBytes -= responseBytesMin; + assert responseBytes >= 0; + + long initialId = correlations.peekLong(); + + KafkaClientStream stream = streamsByInitialIds.get(initialId); + + stream.doStreamData(traceId, flags | FLAG_INIT | FLAG_FIN, sequence, + acknowledge, reserved, buffer, progress, responseBytesMin, extension); + + progress += responseBytesMin; + + if (responseBytes == 0) + { + correlations.remove(); + } + } + } + + private void onConnectionEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = KafkaState.closedReply(state); + + assert replyAck <= replySeq; + + doConnectionEnd(traceId); + + streamsByInitialIds.forEach((k, v) -> v.cleanupStream(traceId)); + } + + private void onConnectionAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + doConnectionAbort(traceId); + + streamsByInitialIds.forEach((k, v) -> v.cleanupStream(traceId)); + } + + private void onConnectionSignal( + SignalFW signal) + { + final int signalId = signal.signalId(); + final int contextId = signal.contextId(); + + if (signalId == SIGNAL_CONNECTION_CLEANUP) + { + doSignalStreamCleanup(); + } + else + { + long initialId = signalerCorrelations.remove(contextId); + KafkaClientStream stream = streamsByInitialIds.get(initialId); + + if (stream != null) + { + stream.onSignal(signal); + } + } + } + + private void onConnectionReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + doConnectionReset(traceId); + + streamsByInitialIds.forEach((k, v) -> v.cleanupStream(traceId)); + } + + private void onConnectionWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int minimum = window.minimum(); + + assert acknowledge <= sequence; + assert sequence <= initialSeq; + assert acknowledge >= initialAck; + assert maximum >= initialMax; + + final int credit = (int)(acknowledge - initialAck) + (maximum - initialMax); + assert credit >= 0; + + this.initialAck = acknowledge; + this.initialMax = maximum; + this.initialMin = minimum; + this.initialPad = padding; + this.initialBud = budgetId; + + assert replyAck <= replySeq; + + if (KafkaState.replyOpening(state)) + { + state = KafkaState.openedReply(state); + if (connectionInitialBudgetId == NO_BUDGET_ID) + { + connectionInitialBudgetId = creditor.acquire(initialId, budgetId); + } + } + + if (connectionInitialBudgetId != NO_BUDGET_ID) + { + creditor.credit(traceId, connectionInitialBudgetId, credit); + } + + streamsByInitialIds.forEach((k, v) -> + v.doStreamWindow(authorization, traceId, connectionInitialBudgetId, initialPad)); + } + + private void doSignalStreamCleanup() + { + this.reconnectAt = signaler.delegate.signalAt( + currentTimeMillis() + 4000, + SIGNAL_CONNECTION_CLEANUP, + this::onStreamCleanupSignal); + } + + + private void onStreamCleanupSignal( + int signalId) + { + assert signalId == SIGNAL_CONNECTION_CLEANUP; + + if (streamsByInitialIds.isEmpty()) + { + final long traceId = supplyTraceId.getAsLong(); + cleanupConnection(traceId); + correlations.clear(); + } + } + + private void cleanupConnection( + long traceId) + { + doConnectionAbort(traceId); + doConnectionReset(traceId); + + cleanupBudgetCreditorIfNecessary(); + } + + private void cleanupBudgetCreditorIfNecessary() + { + if (connectionInitialBudgetId != NO_CREDITOR_INDEX) + { + creditor.release(connectionInitialBudgetId); + connectionInitialBudgetId = NO_CREDITOR_INDEX; + } + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer sender) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + + KafkaClientStream stream = new KafkaClientStream(this, sender, originId, routedId, initialId, authorization); + streamsByInitialIds.put(initialId, stream); + + return stream::onStreamMessage; + } + } +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientDescribeFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientDescribeFactory.java index eb45c1d6b4..d88079723f 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientDescribeFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientDescribeFactory.java @@ -35,11 +35,11 @@ import org.agrona.collections.LongLongConsumer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.String16FW; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFactory.java index 442e015c50..75c397c8b0 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFactory.java @@ -32,6 +32,7 @@ import io.aklivity.zilla.runtime.engine.EngineContext; import io.aklivity.zilla.runtime.engine.binding.BindingHandler; import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.concurrent.Signaler; import io.aklivity.zilla.runtime.engine.config.BindingConfig; public final class KafkaClientFactory implements KafkaStreamFactory @@ -52,26 +53,43 @@ public KafkaClientFactory( final Long2ObjectHashMap bindings = new Long2ObjectHashMap<>(); final KafkaMergedBudgetAccountant accountant = new KafkaMergedBudgetAccountant(context); + final KafkaClientConnectionPool connectionPool = new KafkaClientConnectionPool( + config, context, accountant.creditor()); + + final BindingHandler streamFactory = config.clientConnectionPool() ? connectionPool.streamFactory() : + context.streamFactory(); + + final Signaler signaler = config.clientConnectionPool() ? connectionPool.signaler() : + context.signaler(); + final KafkaClientMetaFactory clientMetaFactory = new KafkaClientMetaFactory( config, context, bindings::get, accountant::supplyDebitor, supplyClientRoute); final KafkaClientDescribeFactory clientDescribeFactory = new KafkaClientDescribeFactory( config, context, bindings::get, accountant::supplyDebitor); + final KafkaClientGroupFactory clientGroupFactory = new KafkaClientGroupFactory( + config, context, bindings::get, accountant::supplyDebitor, signaler, streamFactory); + final KafkaClientFetchFactory clientFetchFactory = new KafkaClientFetchFactory( config, context, bindings::get, accountant::supplyDebitor, supplyClientRoute); final KafkaClientProduceFactory clientProduceFactory = new KafkaClientProduceFactory( config, context, bindings::get, supplyClientRoute); + final KafkaClientOffsetFetchFactory clientOffsetFetchFactory = new KafkaClientOffsetFetchFactory( + config, context, bindings::get, supplyClientRoute); + final KafkaMergedFactory clientMergedFactory = new KafkaMergedFactory( config, context, bindings::get, accountant.creditor()); final Int2ObjectHashMap factories = new Int2ObjectHashMap<>(); factories.put(KafkaBeginExFW.KIND_META, clientMetaFactory); factories.put(KafkaBeginExFW.KIND_DESCRIBE, clientDescribeFactory); + factories.put(KafkaBeginExFW.KIND_GROUP, clientGroupFactory); factories.put(KafkaBeginExFW.KIND_FETCH, clientFetchFactory); factories.put(KafkaBeginExFW.KIND_PRODUCE, clientProduceFactory); + factories.put(KafkaBeginExFW.KIND_OFFSET_FETCH, clientOffsetFetchFactory); factories.put(KafkaBeginExFW.KIND_MERGED, clientMergedFactory); this.kafkaTypeId = context.supplyTypeId(KafkaBinding.NAME); @@ -85,6 +103,9 @@ public void attach( { KafkaBindingConfig kafkaBinding = new KafkaBindingConfig(binding); bindings.put(binding.id, kafkaBinding); + + KafkaClientGroupFactory clientGroupFactory = (KafkaClientGroupFactory) factories.get(KafkaBeginExFW.KIND_GROUP); + clientGroupFactory.onAttached(binding.id); } @Override @@ -92,6 +113,8 @@ public void detach( long bindingId) { bindings.remove(bindingId); + KafkaClientGroupFactory clientGroupFactory = (KafkaClientGroupFactory) factories.get(KafkaBeginExFW.KIND_GROUP); + clientGroupFactory.onDetached(bindingId); } @Override diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFetchFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFetchFactory.java index 31a240f66c..74ebdf8244 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFetchFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientFetchFactory.java @@ -31,11 +31,11 @@ import org.agrona.collections.LongLongConsumer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.kafka.internal.types.KafkaHeaderFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.KafkaIsolation; @@ -1249,9 +1249,9 @@ private int decodeFetchRecord( final int minimum = Math.min(maximum, 1024); int valueClaimed = maximum; - if (valueClaimed != 0 && client.stream.replyDebitorIndex != NO_DEBITOR_INDEX) + if (valueClaimed != 0 && client.stream.replyDebIndex != NO_DEBITOR_INDEX) { - valueClaimed = client.stream.replyDebitor.claim(traceId, client.stream.replyDebitorIndex, + valueClaimed = client.stream.replyDeb.claim(traceId, client.stream.replyDebIndex, client.stream.replyId, minimum, maximum, 0); if (valueClaimed == 0) @@ -1371,9 +1371,9 @@ private int decodeFetchRecordInit( final int minimum = Math.min(maximum, 1024); int valueClaimed = maximum; - if (valueClaimed != 0 && client.stream.replyDebitorIndex != NO_DEBITOR_INDEX) + if (valueClaimed != 0 && client.stream.replyDebIndex != NO_DEBITOR_INDEX) { - valueClaimed = client.stream.replyDebitor.claim(traceId, client.stream.replyDebitorIndex, + valueClaimed = client.stream.replyDeb.claim(traceId, client.stream.replyDebIndex, client.stream.replyId, minimum, maximum, 0); if (valueClaimed == 0) @@ -1449,9 +1449,9 @@ private int decodeFetchRecordValue( final int minimum = Math.min(maximum, 1024); int valueClaimed = maximum; - if (valueClaimed != 0 && client.stream.replyDebitorIndex != NO_DEBITOR_INDEX) + if (valueClaimed != 0 && client.stream.replyDebIndex != NO_DEBITOR_INDEX) { - valueClaimed = client.stream.replyDebitor.claim(traceId, client.stream.replyDebitorIndex, + valueClaimed = client.stream.replyDeb.claim(traceId, client.stream.replyDebIndex, client.stream.replyId, minimum, maximum, 0); if (valueClaimed == 0) @@ -1729,9 +1729,9 @@ private final class KafkaFetchStream private int replyMax; private int replyPad; - private long replyDebitorId; - private BudgetDebitor replyDebitor; - private long replyDebitorIndex = NO_DEBITOR_INDEX; + private long replyBud; + private BudgetDebitor replyDeb; + private long replyDebIndex = NO_DEBITOR_INDEX; KafkaFetchStream( MessageConsumer application, @@ -1866,14 +1866,14 @@ private void onApplicationWindow( this.replyAck = acknowledge; this.replyMax = maximum; this.replyPad = padding; - this.replyDebitorId = budgetId; + this.replyBud = budgetId; assert replyAck <= replySeq; - if (replyDebitorId != 0L && replyDebitor == null) + if (replyBud != 0L && replyDeb == null) { - replyDebitor = supplyDebitor.apply(replyDebitorId); - replyDebitorIndex = replyDebitor.acquire(replyDebitorId, replyId, client::decodeNetworkIfNecessary); + replyDeb = supplyDebitor.apply(replyBud); + replyDebIndex = replyDeb.acquire(replyBud, replyId, client::decodeNetworkIfNecessary); } state = KafkaState.openedReply(state); @@ -1950,7 +1950,7 @@ private void doApplicationData( Flyweight extension) { doData(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, flags, replyDebitorId, reserved, payload, extension); + traceId, authorization, flags, replyBud, reserved, payload, extension); replySeq += reserved; @@ -2101,11 +2101,11 @@ private void cleanupApplication( private void cleanupApplicationDebitorIfNecessary() { - if (replyDebitorIndex != NO_DEBITOR_INDEX) + if (replyDebIndex != NO_DEBITOR_INDEX) { - replyDebitor.release(replyDebitorIndex, replyId); - replyDebitorIndex = NO_DEBITOR_INDEX; - replyDebitor = null; + replyDeb.release(replyDebIndex, replyId); + replyDebIndex = NO_DEBITOR_INDEX; + replyDeb = null; } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientGroupFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientGroupFactory.java new file mode 100644 index 0000000000..6b833a0b7e --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientGroupFactory.java @@ -0,0 +1,4421 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.binding.kafka.internal.types.ProxyAddressProtocol.STREAM; +import static io.aklivity.zilla.runtime.engine.budget.BudgetCreditor.NO_BUDGET_ID; +import static io.aklivity.zilla.runtime.engine.budget.BudgetCreditor.NO_CREDITOR_INDEX; +import static io.aklivity.zilla.runtime.engine.budget.BudgetDebitor.NO_DEBITOR_INDEX; +import static io.aklivity.zilla.runtime.engine.buffer.BufferPool.NO_SLOT; +import static io.aklivity.zilla.runtime.engine.concurrent.Signaler.NO_CANCEL_ID; +import static java.lang.System.currentTimeMillis; +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.nio.ByteOrder; +import java.time.Duration; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.LongFunction; +import java.util.function.Supplier; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.Long2ObjectHashMap; +import org.agrona.collections.LongLongConsumer; +import org.agrona.collections.MutableInteger; +import org.agrona.collections.Object2ObjectHashMap; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Array32FW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.String16FW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.RequestHeaderFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.ResponseHeaderFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.config.ConfigResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.config.DescribeConfigsRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.config.DescribeConfigsResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.config.ResourceRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.config.ResourceResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.consumer.ConsumerAssignmentMetadataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.consumer.ConsumerAssignmentUserdataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.consumer.ConsumerMetadataTopicFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.consumer.ConsumerPartitionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.consumer.ConsumerSubscriptionMetadataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.consumer.ConsumerSubscriptionUserdataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.consumer.ConsumerTopicPartitionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.AssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.FindCoordinatorRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.FindCoordinatorResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.HeartbeatRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.HeartbeatResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.JoinGroupRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.JoinGroupResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.LeaveGroupRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.LeaveGroupResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.LeaveMemberFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.MemberMetadataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.ProtocolMetadataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.SyncGroupRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.SyncGroupResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.rebalance.ConsumerAssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.rebalance.MemberAssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.rebalance.TopicAssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.rebalance.TopicPartitionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaDataExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaFlushExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupFlushExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupMemberFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaGroupMemberMetadataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ProxyBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.SignalFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.budget.BudgetDebitor; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; +import io.aklivity.zilla.runtime.engine.concurrent.Signaler; + +public final class KafkaClientGroupFactory extends KafkaClientSaslHandshaker implements BindingHandler +{ + private static final short METADATA_LOWEST_VERSION = 0; + private static final short ERROR_EXISTS = -1; + private static final short ERROR_NONE = 0; + + private static final short ERROR_COORDINATOR_NOT_AVAILABLE = 15; + private static final short ERROR_NOT_COORDINATOR_FOR_CONSUMER = 16; + private static final short ERROR_UNKNOWN_MEMBER = 25; + private static final short ERROR_MEMBER_ID_REQUIRED = 79; + private static final short ERROR_REBALANCE_IN_PROGRESS = 27; + private static final short SIGNAL_NEXT_REQUEST = 1; + private static final short DESCRIBE_CONFIGS_API_KEY = 32; + private static final short DESCRIBE_CONFIGS_API_VERSION = 0; + private static final byte RESOURCE_TYPE_BROKER = 4; + private static final short FIND_COORDINATOR_API_KEY = 10; + private static final short FIND_COORDINATOR_API_VERSION = 1; + private static final short JOIN_GROUP_API_KEY = 11; + private static final short JOIN_GROUP_VERSION = 5; + private static final short SYNC_GROUP_API_KEY = 14; + private static final short SYNC_GROUP_VERSION = 3; + private static final short LEAVE_GROUP_API_KEY = 13; + private static final short LEAVE_GROUP_VERSION = 3; + private static final short HEARTBEAT_API_KEY = 12; + private static final short HEARTBEAT_VERSION = 3; + + private static final String UNKNOWN_MEMBER_ID = ""; + private static final String HIGHLANDER_PROTOCOL = "highlander"; + private static final String GROUP_MIN_SESSION_TIMEOUT = "group.min.session.timeout.ms"; + private static final String GROUP_MAX_SESSION_TIMEOUT = "group.max.session.timeout.ms"; + private static final byte GROUP_KEY_TYPE = 0x00; + private static final DirectBuffer EMPTY_BUFFER = new UnsafeBuffer(); + private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(EMPTY_BUFFER, 0, 0); + private static final Consumer EMPTY_EXTENSION = ex -> {}; + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final FlushFW flushRO = new FlushFW(); + private final AbortFW abortRO = new AbortFW(); + private final ResetFW resetRO = new ResetFW(); + private final WindowFW windowRO = new WindowFW(); + private final SignalFW signalRO = new SignalFW(); + private final ExtensionFW extensionRO = new ExtensionFW(); + private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); + private final KafkaFlushExFW kafkaFlushExRO = new KafkaFlushExFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); + private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); + private final KafkaResetExFW.Builder kafkaResetExRW = new KafkaResetExFW.Builder(); + private final ProxyBeginExFW.Builder proxyBeginExRW = new ProxyBeginExFW.Builder(); + + private final RequestHeaderFW.Builder requestHeaderRW = new RequestHeaderFW.Builder(); + private final DescribeConfigsRequestFW.Builder describeConfigsRequestRW = new DescribeConfigsRequestFW.Builder(); + private final ResourceRequestFW.Builder resourceRequestRW = new ResourceRequestFW.Builder(); + private final String16FW.Builder configNameRW = new String16FW.Builder(ByteOrder.BIG_ENDIAN); + private final FindCoordinatorRequestFW.Builder findCoordinatorRequestRW = new FindCoordinatorRequestFW.Builder(); + private final JoinGroupRequestFW.Builder joinGroupRequestRW = new JoinGroupRequestFW.Builder(); + private final ProtocolMetadataFW.Builder protocolMetadataRW = new ProtocolMetadataFW.Builder(); + private final SyncGroupRequestFW.Builder syncGroupRequestRW = new SyncGroupRequestFW.Builder(); + private final AssignmentFW.Builder assignmentRW = new AssignmentFW.Builder(); + private final HeartbeatRequestFW.Builder heartbeatRequestRW = new HeartbeatRequestFW.Builder(); + private final LeaveGroupRequestFW.Builder leaveGroupRequestRW = new LeaveGroupRequestFW.Builder(); + private final LeaveMemberFW.Builder leaveMemberRW = new LeaveMemberFW.Builder(); + private final ConsumerSubscriptionMetadataFW.Builder groupSubscriptionMetadataRW = + new ConsumerSubscriptionMetadataFW.Builder(); + private final ConsumerAssignmentMetadataFW.Builder assignmentMetadataRW = new ConsumerAssignmentMetadataFW.Builder(); + private final ConsumerMetadataTopicFW.Builder metadataTopicRW = new ConsumerMetadataTopicFW.Builder(); + private final ConsumerTopicPartitionFW.Builder topicPartitionRW = new ConsumerTopicPartitionFW.Builder(); + private final ConsumerPartitionFW.Builder partitionRW = new ConsumerPartitionFW.Builder(); + private final ConsumerSubscriptionUserdataFW.Builder subscriptionUserdataRW = + new ConsumerSubscriptionUserdataFW.Builder(); + private final ConsumerAssignmentUserdataFW.Builder assignmentUserdataRW = + new ConsumerAssignmentUserdataFW.Builder(); + private final Array32FW memberAssignmentRO = + new Array32FW<>(new MemberAssignmentFW()); + + private final ResourceResponseFW resourceResponseRO = new ResourceResponseFW(); + private final ConfigResponseFW configResponseRO = new ConfigResponseFW(); + private final ResponseHeaderFW responseHeaderRO = new ResponseHeaderFW(); + private final DescribeConfigsResponseFW describeConfigsResponseRO = new DescribeConfigsResponseFW(); + private final FindCoordinatorResponseFW findCoordinatorResponseRO = new FindCoordinatorResponseFW(); + private final JoinGroupResponseFW joinGroupResponseRO = new JoinGroupResponseFW(); + private final MemberMetadataFW memberMetadataRO = new MemberMetadataFW(); + private final SyncGroupResponseFW syncGroupResponseRO = new SyncGroupResponseFW(); + private final HeartbeatResponseFW heartbeatResponseRO = new HeartbeatResponseFW(); + private final LeaveGroupResponseFW leaveGroupResponseRO = new LeaveGroupResponseFW(); + private final LeaveMemberFW leaveMemberRO = new LeaveMemberFW(); + private final Array32FW.Builder topicPartitionsRW = + new Array32FW.Builder<>(new TopicAssignmentFW.Builder(), new TopicAssignmentFW()); + private final ConsumerSubscriptionMetadataFW subscriptionMetadataRO = new ConsumerSubscriptionMetadataFW(); + private final ConsumerAssignmentMetadataFW assignmentMetadataRO = new ConsumerAssignmentMetadataFW(); + private final ConsumerMetadataTopicFW metadataTopicRO = new ConsumerMetadataTopicFW(); + private final ConsumerSubscriptionUserdataFW subscriptionUserdataRO = new ConsumerSubscriptionUserdataFW(); + private final ConsumerAssignmentUserdataFW assignmentUserdataRO = new ConsumerAssignmentUserdataFW(); + private final ConsumerTopicPartitionFW topicPartitionRO = new ConsumerTopicPartitionFW(); + private final ConsumerPartitionFW partitionRO = new ConsumerPartitionFW(); + private final Array32FW assignmentConsumersRO = new Array32FW<>(new ConsumerAssignmentFW()); + private final KafkaGroupMemberMetadataFW kafkaMemberMetadataRO = new KafkaGroupMemberMetadataFW(); + + private final KafkaDescribeClientDecoder decodeSaslHandshakeResponse = this::decodeSaslHandshakeResponse; + private final KafkaDescribeClientDecoder decodeSaslHandshake = this::decodeSaslHandshake; + private final KafkaDescribeClientDecoder decodeSaslHandshakeMechanisms = this::decodeSaslHandshakeMechanisms; + private final KafkaDescribeClientDecoder decodeSaslHandshakeMechanism = this::decodeSaslHandshakeMechanism; + private final KafkaDescribeClientDecoder decodeSaslAuthenticateResponse = this::decodeSaslAuthenticateResponse; + private final KafkaDescribeClientDecoder decodeSaslAuthenticate = this::decodeSaslAuthenticate; + private final KafkaDescribeClientDecoder decodeDescribeResponse = this::decodeDescribeResponse; + private final KafkaDescribeClientDecoder decodeIgnoreAll = this::decodeIgnoreAll; + private final KafkaDescribeClientDecoder decodeReject = this::decodeReject; + private final KafkaGroupClusterClientDecoder decodeClusterSaslHandshakeResponse = this::decodeSaslHandshakeResponse; + private final KafkaGroupClusterClientDecoder decodeClusterSaslHandshake = this::decodeSaslHandshake; + private final KafkaGroupClusterClientDecoder decodeClusterSaslHandshakeMechanisms = this::decodeSaslHandshakeMechanisms; + private final KafkaGroupClusterClientDecoder decodeClusterSaslHandshakeMechanism = this::decodeSaslHandshakeMechanism; + private final KafkaGroupClusterClientDecoder decodeClusterSaslAuthenticateResponse = this::decodeSaslAuthenticateResponse; + private final KafkaGroupClusterClientDecoder decodeClusterSaslAuthenticate = this::decodeSaslAuthenticate; + private final KafkaGroupClusterClientDecoder decodeFindCoordinatorResponse = this::decodeFindCoordinatorResponse; + private final KafkaGroupClusterClientDecoder decodeClusterReject = this::decodeClusterReject; + private final KafkaGroupClusterClientDecoder decodeClusterIgnoreAll = this::decodeIgnoreAll; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorSaslHandshakeResponse = + this::decodeSaslHandshakeResponse; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorSaslHandshake = + this::decodeSaslHandshake; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorSaslHandshakeMechanisms = + this::decodeSaslHandshakeMechanisms; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorSaslHandshakeMechanism = + this::decodeSaslHandshakeMechanism; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorSaslAuthenticateResponse = + this::decodeSaslAuthenticateResponse; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorSaslAuthenticate = + this::decodeSaslAuthenticate; + private final KafkaGroupCoordinatorClientDecoder decodeJoinGroupResponse = + this::decodeJoinGroupResponse; + private final KafkaGroupCoordinatorClientDecoder decodeSyncGroupResponse = + this::decodeSyncGroupResponse; + private final KafkaGroupCoordinatorClientDecoder decodeHeartbeatResponse = + this::decodeHeartbeatResponse; + private final KafkaGroupCoordinatorClientDecoder decodeLeaveGroupResponse = + this::decodeLeaveGroupResponse; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorIgnoreAll = this::decodeIgnoreAll; + private final KafkaGroupCoordinatorClientDecoder decodeCoordinatorReject = this::decodeCoordinatorReject; + + private final Map configs = new LinkedHashMap<>(); + private final int kafkaTypeId; + private final int proxyTypeId; + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final BufferPool decodePool; + private final BufferPool encodePool; + private final Signaler signaler; + private final BindingHandler streamFactory; + private final LongFunction supplyBinding; + private final Supplier supplyInstanceId; + private final LongFunction supplyDebitor; + private final Long2ObjectHashMap instanceIds; + private final Object2ObjectHashMap groupStreams; + private final String clientId; + private final Duration rebalanceTimeout; + + + public KafkaClientGroupFactory( + KafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding, + LongFunction supplyDebitor, + Signaler signaler, + BindingHandler streamFactory) + { + super(config, context); + this.kafkaTypeId = context.supplyTypeId(KafkaBinding.NAME); + this.proxyTypeId = context.supplyTypeId("proxy"); + this.signaler = signaler; + this.streamFactory = streamFactory; + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.decodePool = context.bufferPool(); + this.encodePool = context.bufferPool(); + this.supplyBinding = supplyBinding; + this.rebalanceTimeout = config.clientGroupRebalanceTimeout(); + this.clientId = config.clientId(); + this.supplyInstanceId = config.clientInstanceIdSupplier(); + this.supplyDebitor = supplyDebitor; + this.instanceIds = new Long2ObjectHashMap<>(); + this.groupStreams = new Object2ObjectHashMap<>(); + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer application) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long affinity = begin.affinity(); + final long authorization = begin.authorization(); + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extensionRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()); + final KafkaBeginExFW kafkaBeginEx = beginEx != null && beginEx.typeId() == kafkaTypeId ? + kafkaBeginExRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()) : null; + + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_GROUP; + final KafkaGroupBeginExFW kafkaGroupBeginEx = kafkaBeginEx.group(); + + MessageConsumer newStream = null; + + final KafkaBindingConfig binding = supplyBinding.apply(routedId); + final KafkaRouteConfig resolved; + final int timeout = Math.min(kafkaGroupBeginEx.timeout(), 30_000); + final String groupId = kafkaGroupBeginEx.groupId().asString(); + final String protocol = kafkaGroupBeginEx.protocol().asString(); + + if (binding != null) + { + resolved = binding.resolve(authorization, null, groupId); + + if (resolved != null) + { + final long resolvedId = resolved.id; + final KafkaSaslConfig sasl = binding.sasl(); + + final GroupMembership groupMembership = instanceIds.get(binding.id); + assert groupMembership != null; + + KafkaGroupStream group = groupStreams.get(groupId); + + if (group == null) + { + KafkaGroupStream newGroup = new KafkaGroupStream( + application, + originId, + routedId, + initialId, + affinity, + resolvedId, + groupId, + protocol, + timeout, + groupMembership, + sasl); + newStream = newGroup::onApplication; + + groupStreams.put(groupId, newGroup); + } + else if (HIGHLANDER_PROTOCOL.equals(protocol)) + { + group.onApplicationMigrate(begin, application); + newStream = group::onApplication; + } + } + } + + return newStream; + } + + public void onAttached( + long bindingId) + { + instanceIds.put(bindingId, new GroupMembership(supplyInstanceId.get())); + } + + public void onDetached( + long bindingId) + { + instanceIds.remove(bindingId); + } + + private MessageConsumer newStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + final MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer payload, + int offset, + int length, + Consumer extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload, offset, length) + .extension(extension) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doDataEmpty( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Consumer extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .payload(EMPTY_OCTETS) + .extension(extension) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Consumer extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Flyweight extension) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + @FunctionalInterface + private interface KafkaGroupClusterClientDecoder + { + int decode( + ClusterClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int progress, + int limit); + } + + @FunctionalInterface + private interface KafkaDescribeClientDecoder + { + int decode( + DescribeClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int progress, + int limit); + } + + @FunctionalInterface + private interface KafkaGroupCoordinatorClientDecoder + { + int decode( + CoordinatorClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int progress, + int limit); + } + + private int decodeDescribeResponse( + DescribeClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.tryWrap(buffer, progress, limit); + if (responseHeader == null) + { + client.decoder = decodeIgnoreAll; + break decode; + } + + final int responseSize = responseHeader.length(); + + if (length >= responseHeader.sizeof() + responseSize) + { + progress = responseHeader.limit(); + + final DescribeConfigsResponseFW describeConfigsResponse = + describeConfigsResponseRO.tryWrap(buffer, progress, limit); + + if (describeConfigsResponse == null) + { + client.decoder = decodeIgnoreAll; + break decode; + } + + progress = describeConfigsResponse.limit(); + + final int resourceCount = describeConfigsResponse.resourceCount(); + for (int resourceIndex = 0; resourceIndex < resourceCount; resourceIndex++) + { + final ResourceResponseFW resource = resourceResponseRO.tryWrap(buffer, progress, limit); + if (resource == null) + { + client.decoder = decodeIgnoreAll; + break decode; + } + + progress = resource.limit(); + + final String resourceName = resource.name().asString(); + final int resourceError = resource.errorCode(); + + client.onDecodeResource(traceId, client.authorization, resourceError, resourceName); + // TODO: use different decoder for configs + if (resourceError != ERROR_NONE || !client.delegate.nodeId.equals(resourceName)) + { + client.decoder = decodeIgnoreAll; + break decode; + } + + final int configCount = resource.configCount(); + configs.clear(); + for (int configIndex = 0; configIndex < configCount; configIndex++) + { + final ConfigResponseFW config = configResponseRO.tryWrap(buffer, progress, limit); + if (config == null) + { + client.decoder = decodeIgnoreAll; + break decode; + } + + progress = config.limit(); + + final String name = config.name().asString(); + final String value = config.value().asString(); + + configs.put(name, value); + } + + client.onDecodeDescribeResponse(traceId, configs); + } + } + } + + if (client.decoder == decodeIgnoreAll) + { + client.cleanupNetwork(traceId); + } + + return progress; + } + + private int decodeReject( + DescribeClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + client.doNetworkReset(traceId); + client.decoder = decodeIgnoreAll; + return limit; + } + + private int decodeFindCoordinatorResponse( + ClusterClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.tryWrap(buffer, progress, limit); + if (responseHeader == null) + { + client.decoder = decodeClusterIgnoreAll; + break decode; + } + + final int responseSize = responseHeader.length(); + + if (length >= responseHeader.sizeof() + responseSize) + { + progress = responseHeader.limit(); + + final FindCoordinatorResponseFW findCoordinatorResponse = + findCoordinatorResponseRO.tryWrap(buffer, progress, limit); + + if (findCoordinatorResponse == null) + { + client.decoder = decodeClusterIgnoreAll; + break decode; + } + else if (findCoordinatorResponse.errorCode() == ERROR_COORDINATOR_NOT_AVAILABLE) + { + client.onCoordinatorNotAvailable(traceId, authorization); + } + else if (findCoordinatorResponse.errorCode() == ERROR_NONE) + { + client.onFindCoordinator(traceId, authorization, findCoordinatorResponse.nodeId(), + findCoordinatorResponse.host(), findCoordinatorResponse.port()); + } + else + { + client.decoder = decodeClusterIgnoreAll; + } + + progress = findCoordinatorResponse.limit(); + } + } + + if (client.decoder == decodeClusterIgnoreAll) + { + client.onError(traceId); + } + + return progress; + } + + + private int decodeClusterReject( + ClusterClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + client.doNetworkReset(traceId); + client.decoder = decodeClusterIgnoreAll; + return limit; + } + + private int decodeCoordinatorReject( + CoordinatorClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + client.doNetworkReset(traceId); + client.decoder = decodeCoordinatorIgnoreAll; + return limit; + } + + private int decodeIgnoreAll( + KafkaSaslClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + return limit; + } + + private int decodeJoinGroupResponse( + CoordinatorClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.tryWrap(buffer, progress, limit); + if (responseHeader == null) + { + client.decoder = decodeJoinGroupResponse; + progress = limit; + break decode; + } + + final int responseSize = responseHeader.length(); + + if (length >= responseHeader.sizeof() + responseSize) + { + progress = responseHeader.limit(); + + final JoinGroupResponseFW joinGroupResponse = + joinGroupResponseRO.tryWrap(buffer, progress, limit); + + final short errorCode = joinGroupResponse != null ? joinGroupResponse.errorCode() : ERROR_EXISTS; + + if (joinGroupResponse == null) + { + client.decoder = decodeJoinGroupResponse; + progress = limit; + break decode; + } + else if (errorCode == ERROR_NOT_COORDINATOR_FOR_CONSUMER) + { + client.onNotCoordinatorError(traceId, authorization); + progress = joinGroupResponse.limit(); + } + else if (errorCode == ERROR_UNKNOWN_MEMBER) + { + client.onJoinGroupMemberIdError(traceId, authorization, UNKNOWN_MEMBER_ID); + progress = joinGroupResponse.limit(); + } + else if (errorCode == ERROR_MEMBER_ID_REQUIRED) + { + client.onJoinGroupMemberIdError(traceId, authorization, + joinGroupResponse.memberId().asString()); + progress = joinGroupResponse.limit(); + } + else if (errorCode == ERROR_NONE) + { + progress = joinGroupResponse.limit(); + client.members.clear(); + + client.generationId = joinGroupResponse.generatedId(); + + metadata: + for (int i = 0; i < joinGroupResponse.memberCount(); i++) + { + final MemberMetadataFW memberMetadata = memberMetadataRO.tryWrap(buffer, progress, limit); + if (memberMetadata != null) + { + client.members.add(new MemberProtocol( + memberMetadata.memberId().asString(), memberMetadata.metadata())); + progress = memberMetadata.limit(); + } + else + { + break metadata; + } + } + + client.onJoinGroupResponse(traceId, authorization, joinGroupResponse.leader().asString(), + joinGroupResponse.memberId().asString()); + } + else + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + + } + } + + if (client.decoder == decodeCoordinatorIgnoreAll) + { + client.onError(traceId); + } + + return progress; + } + + private int decodeSyncGroupResponse( + CoordinatorClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.tryWrap(buffer, progress, limit); + if (responseHeader == null) + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + + final int responseSize = responseHeader.length(); + + if (length >= responseHeader.sizeof() + responseSize) + { + progress = responseHeader.limit(); + + final SyncGroupResponseFW syncGroupResponse = + syncGroupResponseRO.tryWrap(buffer, progress, limit); + + final short errorCode = syncGroupResponse != null ? syncGroupResponse.errorCode() : ERROR_EXISTS; + + if (syncGroupResponse == null) + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + else if (errorCode == ERROR_REBALANCE_IN_PROGRESS) + { + client.onSynGroupRebalance(traceId, authorization); + } + else if (errorCode == ERROR_NONE) + { + client.onSyncGroupResponse(traceId, authorization, syncGroupResponse.assignment()); + } + else + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + + progress = syncGroupResponse.limit(); + } + } + + if (client.decoder == decodeCoordinatorIgnoreAll) + { + client.onError(traceId); + } + + return progress; + } + + private int decodeHeartbeatResponse( + CoordinatorClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.tryWrap(buffer, progress, limit); + if (responseHeader == null) + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + + final int responseSize = responseHeader.length(); + + if (length >= responseHeader.sizeof() + responseSize) + { + progress = responseHeader.limit(); + + final HeartbeatResponseFW heartbeatResponse = + heartbeatResponseRO.tryWrap(buffer, progress, limit); + + if (heartbeatResponse == null) + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + else if (heartbeatResponse.errorCode() == ERROR_REBALANCE_IN_PROGRESS) + { + client.onRebalanceError(traceId, authorization); + } + else if (heartbeatResponse.errorCode() == ERROR_NONE) + { + client.onHeartbeatResponse(traceId, authorization); + } + else + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + + progress = heartbeatResponse.limit(); + } + } + + if (client.decoder == decodeCoordinatorIgnoreAll) + { + client.onError(traceId); + } + + return progress; + } + + private int decodeLeaveGroupResponse( + CoordinatorClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.tryWrap(buffer, progress, limit); + if (responseHeader == null) + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + + final int responseSize = responseHeader.length(); + + if (length >= responseHeader.sizeof() + responseSize) + { + progress = responseHeader.limit(); + + final LeaveGroupResponseFW leaveGroupResponse = + leaveGroupResponseRO.tryWrap(buffer, progress, limit); + + if (leaveGroupResponse == null) + { + client.decoder = decodeCoordinatorIgnoreAll; + break decode; + } + else + { + progress = leaveGroupResponse.limit(); + + members: + for (int i = 0; i < leaveGroupResponse.memberCount(); i++) + { + final LeaveMemberFW member = leaveMemberRO.tryWrap(buffer, progress, limit); + if (member != null) + { + progress = member.limit(); + } + else + { + break members; + } + } + + client.onLeaveGroupResponse(traceId, authorization); + } + } + } + + if (client.decoder == decodeCoordinatorIgnoreAll) + { + client.onError(traceId); + } + + return progress; + } + + private final class KafkaGroupStream + { + private final ClusterClient clusterClient; + private final DescribeClient describeClient; + private final CoordinatorClient coordinatorClient; + private final GroupMembership groupMembership; + private final String groupId; + private final String protocol; + private final long resolvedId; + + private MessageConsumer application; + private String host; + private String nodeId; + private int port; + private int timeout; + private MutableDirectBuffer metadataBuffer; + + private int state; + + private long originId; + private long routedId; + private long initialId; + private long replyId; + private long affinity; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private long replyBudgetId; + private int topicMetadataLimit; + + KafkaGroupStream( + MessageConsumer application, + long originId, + long routedId, + long initialId, + long affinity, + long resolvedId, + String groupId, + String protocol, + int timeout, + GroupMembership groupMembership, + KafkaSaslConfig sasl) + { + this.application = application; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.affinity = affinity; + this.groupId = groupId; + this.protocol = protocol; + this.timeout = timeout; + this.resolvedId = resolvedId; + this.groupMembership = groupMembership; + this.clusterClient = new ClusterClient(routedId, resolvedId, sasl, this); + this.describeClient = new DescribeClient(routedId, resolvedId, sasl, this); + this.coordinatorClient = new CoordinatorClient(routedId, resolvedId, sasl, this); + this.metadataBuffer = new UnsafeBuffer(new byte[2048]); + } + + private void onApplication( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onApplicationBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onApplicationData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onApplicationFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onApplicationEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onApplicationAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onApplicationWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onApplicationReset(reset); + break; + default: + break; + } + } + + private void onApplicationBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extensionRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()); + final KafkaBeginExFW kafkaBeginEx = beginEx != null && beginEx.typeId() == kafkaTypeId ? + kafkaBeginExRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()) : null; + + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_GROUP; + final KafkaGroupBeginExFW kafkaGroupBeginEx = kafkaBeginEx.group(); + + OctetsFW metadata = kafkaGroupBeginEx.metadata(); + final int metadataSize = kafkaGroupBeginEx.metadataLen(); + + if (metadataSize > 0) + { + metadataBuffer.putBytes(0, metadata.value(), 0, metadataSize); + topicMetadataLimit += metadataSize; + } + + state = KafkaState.openingInitial(state); + + if (coordinatorClient.nextJoinGroupRequestId == 0) + { + clusterClient.doNetworkBeginIfNecessary(traceId, authorization, affinity); + } + + doApplicationWindow(traceId, 0L, 0, 0, 0); + } + + private void onApplicationData( + DataFW data) + { + final long traceId = data.traceId(); + final long budgetId = data.budgetId(); + + coordinatorClient.doSyncRequest(traceId, budgetId, data.payload()); + } + + private void onApplicationEnd( + EndFW end) + { + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + state = KafkaState.closingInitial(state); + coordinatorClient.doLeaveGroupRequest(traceId); + } + + private void onApplicationFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorizationId = flush.authorization(); + final int reserved = flush.reserved(); + final OctetsFW extension = flush.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence + reserved; + initialAck = initialSeq; + + if (extension.sizeof() > 0) + { + final ExtensionFW beginEx = extensionRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()); + final KafkaFlushExFW kafkaFlushEx = beginEx != null && beginEx.typeId() == kafkaTypeId ? + kafkaFlushExRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()) : null; + + assert kafkaFlushEx.kind() == KafkaBeginExFW.KIND_GROUP; + final KafkaGroupFlushExFW kafkaGroupFlushEx = kafkaFlushEx.group(); + + Array32FW members = kafkaGroupFlushEx.members(); + + assert members.fieldCount() == 1; + + members.forEach(m -> + { + OctetsFW metadata = m.metadata(); + final int metadataSize = m.metadataLen(); + + if (metadataSize > 0) + { + metadataBuffer.putBytes(0, metadata.value(), 0, metadataSize); + topicMetadataLimit = metadataSize; + } + }); + + coordinatorClient.doJoinGroupRequest(traceId); + } + else + { + coordinatorClient.doHeartbeat(traceId); + } + } + + private void onApplicationAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + state = KafkaState.closedInitial(state); + + clusterClient.doNetworkAbort(traceId); + coordinatorClient.doNetworkAbort(traceId); + + cleanupApplication(traceId, EMPTY_OCTETS); + } + + private void onApplicationWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + this.replyAck = acknowledge; + this.replyMax = maximum; + this.replyPad = padding; + this.replyBudgetId = budgetId; + + assert replyAck <= replySeq; + } + + private void onApplicationReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + clusterClient.doNetworkReset(traceId); + } + + private boolean isApplicationReplyOpen() + { + return KafkaState.replyOpening(state); + } + + private void doApplicationBeginIfNecessary( + long traceId, + long authorization) + { + if (!KafkaState.replyOpening(state)) + { + doApplicationBegin(traceId, authorization); + } + } + + private void doApplicationBegin( + long traceId, + long authorization) + { + state = KafkaState.openingReply(state); + + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .group(g -> g + .groupId(groupId) + .protocol(protocol) + .timeout(timeout)) + .build(); + + doBegin(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, kafkaBeginEx); + } + + private void doApplicationData( + long traceId, + long authorization, + DirectBuffer buffer, + int offset, + int length) + { + final int reserved = replyPad; + + if (length > 0) + { + doData(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, reserved, buffer, offset, length, EMPTY_EXTENSION); + } + else + { + doDataEmpty(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, reserved, EMPTY_EXTENSION); + } + + replySeq += reserved; + + assert replyAck <= replySeq; + } + + private void doApplicationFlush( + long traceId, + long authorization, + Consumer extension) + { + if (!KafkaState.replyClosed(state)) + { + final int reserved = replyPad; + + doFlush(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, reserved, extension); + } + } + + private void doApplicationEnd( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + state = KafkaState.closedReply(state); + doEnd(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, 0, EMPTY_EXTENSION); + } + } + + private void doApplicationAbort( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + state = KafkaState.closedReply(state); + doAbort(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, 0, EMPTY_EXTENSION); + } + } + + private void doApplicationWindow( + long traceId, + long budgetId, + int minInitialNoAck, + int minInitialPad, + int minInitialMax) + { + final long newInitialAck = Math.max(initialSeq - minInitialNoAck, initialAck); + + if (newInitialAck > initialAck || minInitialMax > initialMax || !KafkaState.initialOpened(state)) + { + initialAck = newInitialAck; + assert initialAck <= initialSeq; + + initialMax = minInitialMax; + + state = KafkaState.openedInitial(state); + + doWindow(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, clusterClient.authorization, budgetId, minInitialPad); + } + } + + private void doApplicationReset( + long traceId, + Flyweight extension) + { + state = KafkaState.closedInitial(state); + + doReset(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, clusterClient.authorization, extension); + } + + private void doApplicationAbortIfNecessary( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doApplicationAbort(traceId); + } + } + + private void doApplicationResetIfNecessary( + long traceId, + Flyweight extension) + { + if (!KafkaState.initialClosed(state)) + { + doApplicationReset(traceId, extension); + } + } + + private void onNotCoordinatorError( + long traceId, + long authority) + { + clusterClient.doNetworkBeginIfNecessary(traceId, authority, affinity); + } + + private void cleanupApplication( + long traceId, + int error) + { + final KafkaResetExFW kafkaResetEx = kafkaResetExRW.wrap(writeBuffer, + ResetFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .error(error) + .build(); + + cleanupApplication(traceId, kafkaResetEx); + } + + private void cleanupApplication( + long traceId, + Flyweight extension) + { + doApplicationResetIfNecessary(traceId, extension); + doApplicationAbortIfNecessary(traceId); + + groupStreams.remove(groupId); + } + + private void onApplicationMigrate( + BeginFW begin, + MessageConsumer application) + { + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long affinity = begin.affinity(); + final long traceId = begin.traceId(); + + doApplicationResetIfNecessary(traceId, EMPTY_OCTETS); + doApplicationAbortIfNecessary(traceId); + + this.application = application; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.affinity = affinity; + + if (KafkaState.closed(state)) + { + initialSeq = 0; + initialAck = 0; + replyAck = 0; + replySeq = 0; + state = 0; + } + + coordinatorClient.doJoinGroupRequest(traceId); + } + } + + private final class ClusterClient extends KafkaSaslClient + { + private final LongLongConsumer encodeSaslHandshakeRequest = this::doEncodeSaslHandshakeRequest; + private final LongLongConsumer encodeSaslAuthenticateRequest = this::doEncodeSaslAuthenticateRequest; + private final LongLongConsumer encodeFindCoordinatorRequest = this::doEncodeFindCoordinatorRequest; + private final KafkaGroupStream delegate; + + private MessageConsumer network; + + private int state; + private long authorization; + + private long initialSeq; + private long initialAck; + private int initialMin; + private int initialMax; + private int initialPad; + private long initialBudgetId = NO_BUDGET_ID; + private long initialDebIndex = NO_DEBITOR_INDEX; + + private long replySeq; + private long replyAck; + private long replyBud; + private int replyMax; + + private int encodeSlot = NO_SLOT; + private int encodeSlotOffset; + private long encodeSlotTraceId; + + private int decodeSlot = NO_SLOT; + private int decodeSlotOffset; + private int decodeSlotReserved; + + private int nextResponseId; + + private BudgetDebitor initialDeb; + private KafkaGroupClusterClientDecoder decoder; + private LongLongConsumer encoder; + + ClusterClient( + long originId, + long routedId, + KafkaSaslConfig sasl, + KafkaGroupStream delegate) + { + super(sasl, originId, routedId); + + this.encoder = sasl != null ? encodeSaslHandshakeRequest : encodeFindCoordinatorRequest; + this.delegate = delegate; + this.decoder = decodeClusterReject; + } + + private void onNetwork( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onNetworkBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onNetworkData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onNetworkEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onNetworkAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onNetworkReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onNetworkWindow(window); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onNetworkSignal(signal); + break; + default: + break; + } + } + + private void onNetworkBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + authorization = begin.authorization(); + state = KafkaState.openingReply(state); + + doNetworkWindow(traceId, 0L, 0, 0, decodePool.slotCapacity()); + } + + private void onNetworkData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long budgetId = data.budgetId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + data.reserved(); + authorization = data.authorization(); + replyBud = budgetId; + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + onError(traceId); + } + else + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + onError(traceId); + } + else + { + final OctetsFW payload = data.payload(); + int reserved = data.reserved(); + int offset = payload.offset(); + int limit = payload.limit(); + + final MutableDirectBuffer buffer = decodePool.buffer(decodeSlot); + buffer.putBytes(decodeSlotOffset, payload.buffer(), offset, limit - offset); + decodeSlotOffset += limit - offset; + decodeSlotReserved += reserved; + + offset = 0; + limit = decodeSlotOffset; + reserved = decodeSlotReserved; + + decodeNetwork(traceId, authorization, budgetId, reserved, buffer, offset, limit); + } + } + } + + private void onNetworkEnd( + EndFW end) + { + state = KafkaState.closedReply(state); + + cleanupDecodeSlotIfNecessary(); + } + + private void onNetworkAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedReply(state); + + onError(traceId); + } + + private void onNetworkReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + onError(traceId); + } + + private void onNetworkWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int minimum = window.minimum(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= initialSeq; + assert acknowledge >= initialAck; + assert maximum + acknowledge >= initialMax + initialAck; + + this.initialAck = acknowledge; + this.initialMax = maximum; + this.initialPad = padding; + this.initialMin = minimum; + this.initialBudgetId = budgetId; + + assert initialAck <= initialSeq; + + this.authorization = window.authorization(); + + state = KafkaState.openedInitial(state); + + if (initialBudgetId != NO_BUDGET_ID && initialDebIndex == NO_DEBITOR_INDEX) + { + initialDeb = supplyDebitor.apply(initialBudgetId); + initialDebIndex = initialDeb.acquire(initialBudgetId, initialId, this::doNetworkDataIfNecessary); + assert initialDebIndex != NO_DEBITOR_INDEX; + } + + doNetworkDataIfNecessary(budgetId); + + doEncodeRequestIfNecessary(traceId, budgetId); + } + + private void doNetworkDataIfNecessary( + long traceId) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer buffer = encodePool.buffer(encodeSlot); + final int limit = encodeSlotOffset; + + encodeNetwork(traceId, authorization, initialBudgetId, buffer, 0, limit); + } + } + + private void onNetworkSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final int signalId = signal.signalId(); + + if (signalId == SIGNAL_NEXT_REQUEST) + { + doEncodeRequestIfNecessary(traceId, initialBudgetId); + } + } + + private void doNetworkBeginIfNecessary( + long traceId, + long authorization, + long affinity) + { + if (KafkaState.closed(state)) + { + replyAck = 0; + replySeq = 0; + state = 0; + } + + if (!KafkaState.initialOpening(state)) + { + doNetworkBegin(traceId, authorization, affinity); + } + } + + private void doNetworkBegin( + long traceId, + long authorization, + long affinity) + { + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + state = KafkaState.openingInitial(state); + + network = newStream(this::onNetwork, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, EMPTY_EXTENSION); + } + + @Override + protected void doNetworkData( + long traceId, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(encodeSlotOffset, buffer, offset, limit - offset); + encodeSlotOffset += limit - offset; + encodeSlotTraceId = traceId; + + buffer = encodeBuffer; + offset = 0; + limit = encodeSlotOffset; + } + + encodeNetwork(traceId, authorization, budgetId, buffer, offset, limit); + } + + private void doNetworkEnd( + long traceId, + long authorization) + { + if (!KafkaState.initialClosed(state)) + { + state = KafkaState.closedInitial(state); + + doEnd(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + } + + cleanupEncodeSlotIfNecessary(); + } + + private void doNetworkAbort( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doAbort(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + state = KafkaState.closedInitial(state); + } + + cleanupEncodeSlotIfNecessary(); + } + + private void doNetworkReset( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doReset(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + state = KafkaState.closedReply(state); + } + + cleanupDecodeSlotIfNecessary(); + } + + private void doNetworkWindow( + long traceId, + long budgetId, + int minReplyNoAck, + int minReplyPad, + int minReplyMax) + { + final long newReplyAck = Math.max(replySeq - minReplyNoAck, replyAck); + + if (newReplyAck > replyAck || minReplyMax > replyMax || !KafkaState.replyOpened(state)) + { + replyAck = newReplyAck; + assert replyAck <= replySeq; + + replyMax = minReplyMax; + + state = KafkaState.openedReply(state); + + doWindow(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, minReplyPad); + } + } + + private void doEncodeRequestIfNecessary( + long traceId, + long budgetId) + { + if (nextRequestId == nextResponseId) + { + encoder.accept(traceId, budgetId); + } + } + + private void doEncodeFindCoordinatorRequest( + long traceId, + long budgetId) + { + final MutableDirectBuffer encodeBuffer = writeBuffer; + final int encodeOffset = DataFW.FIELD_OFFSET_PAYLOAD; + final int encodeLimit = encodeBuffer.capacity(); + + int encodeProgress = encodeOffset; + + final RequestHeaderFW requestHeader = requestHeaderRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .length(0) + .apiKey(FIND_COORDINATOR_API_KEY) + .apiVersion(FIND_COORDINATOR_API_VERSION) + .correlationId(0) + .clientId(clientId) + .build(); + + encodeProgress = requestHeader.limit(); + + final FindCoordinatorRequestFW findCoordinatorRequest = + findCoordinatorRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .key(delegate.groupId) + .keyType(GROUP_KEY_TYPE) + .build(); + + encodeProgress = findCoordinatorRequest.limit(); + + final int requestId = nextRequestId++; + final int requestSize = encodeProgress - encodeOffset - RequestHeaderFW.FIELD_OFFSET_API_KEY; + + requestHeaderRW.wrap(encodeBuffer, requestHeader.offset(), requestHeader.limit()) + .length(requestSize) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId().asString()) + .build(); + + doNetworkData(traceId, budgetId, encodeBuffer, encodeOffset, encodeProgress); + + decoder = decodeFindCoordinatorResponse; + } + + private void encodeNetwork( + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + final int length = limit - offset; + final int lengthMin = Math.min(length, 1024); + final int initialBudget = Math.max(initialMax - (int)(initialSeq - initialAck), 0); + final int reservedMax = Math.max(Math.min(length + initialPad, initialBudget), initialMin); + final int reservedMin = Math.max(Math.min(lengthMin + initialPad, reservedMax), initialMin); + + int reserved = reservedMax; + + flush: + if (reserved > 0) + { + + boolean claimed = false; + + if (initialDebIndex != NO_DEBITOR_INDEX) + { + final int lengthMax = Math.min(reserved - initialPad, length); + final int deferredMax = length - lengthMax; + reserved = initialDeb.claim(traceId, initialDebIndex, initialId, reservedMin, reserved, deferredMax); + claimed = reserved > 0; + } + + if (reserved < initialPad || reserved == initialPad && length > 0) + { + break flush; + } + + doData(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, buffer, offset, length, EMPTY_EXTENSION); + + initialSeq += reserved; + + assert initialAck <= initialSeq; + } + + final int flushed = Math.max(reserved - initialPad, 0); + final int remaining = length - flushed; + if (remaining > 0) + { + if (encodeSlot == NO_SLOT) + { + encodeSlot = encodePool.acquire(initialId); + } + + if (encodeSlot == NO_SLOT) + { + onError(traceId); + } + else + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(0, buffer, offset + flushed, remaining); + encodeSlotOffset = remaining; + } + } + else + { + cleanupEncodeSlotIfNecessary(); + } + } + + private void decodeNetwork( + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int limit) + { + KafkaGroupClusterClientDecoder previous = null; + int progress = offset; + while (progress <= limit && previous != decoder) + { + previous = decoder; + progress = decoder.decode(this, traceId, authorization, budgetId, reserved, buffer, offset, progress, limit); + } + + if (progress < limit) + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + onError(traceId); + } + else + { + final MutableDirectBuffer decodeBuffer = decodePool.buffer(decodeSlot); + decodeBuffer.putBytes(0, buffer, progress, limit - progress); + decodeSlotOffset = limit - progress; + decodeSlotReserved = (limit - progress) * reserved / (limit - offset); + } + + doNetworkWindow(traceId, budgetId, decodeSlotOffset, 0, replyMax); + } + else + { + cleanupDecodeSlotIfNecessary(); + + if (reserved > 0) + { + doNetworkWindow(traceId, budgetId, 0, 0, replyMax); + } + } + } + + @Override + protected void doDecodeSaslHandshakeResponse( + long traceId) + { + decoder = decodeClusterSaslHandshakeResponse; + } + + @Override + protected void doDecodeSaslHandshake( + long traceId) + { + decoder = decodeClusterSaslHandshake; + } + + @Override + protected void doDecodeSaslHandshakeMechanisms( + long traceId) + { + decoder = decodeClusterSaslHandshakeMechanisms; + } + + @Override + protected void doDecodeSaslHandshakeMechansim( + long traceId) + { + decoder = decodeClusterSaslHandshakeMechanism; + } + + @Override + protected void doDecodeSaslAuthenticateResponse( + long traceId) + { + decoder = decodeClusterSaslAuthenticateResponse; + } + + @Override + protected void doDecodeSaslAuthenticate( + long traceId) + { + decoder = decodeClusterSaslAuthenticate; + } + + @Override + protected void onDecodeSaslHandshakeResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + encoder = encodeSaslAuthenticateRequest; + decoder = decodeClusterSaslAuthenticateResponse; + break; + default: + delegate.cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslAuthenticateResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + encoder = encodeFindCoordinatorRequest; + decoder = decodeFindCoordinatorResponse; + break; + default: + delegate.cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslResponse( + long traceId) + { + nextResponseId++; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onCoordinatorNotAvailable( + long traceId, + long authorization) + { + nextResponseId++; + + encoder = encodeFindCoordinatorRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onFindCoordinator( + long traceId, + long authorization, + int nodeId, + String16FW host, + int port) + { + nextResponseId++; + + delegate.nodeId = String.valueOf(nodeId); + delegate.host = host.asString(); + delegate.port = port; + + delegate.describeClient.doNetworkBegin(traceId, authorization, 0); + + cleanupNetwork(traceId, authorization); + } + + private void cleanupNetwork( + long traceId, + long authorization) + { + replySeq = 0; + replyAck = 0; + + doNetworkEnd(traceId, authorization); + doNetworkReset(traceId); + } + + private void onError( + long traceId) + { + doNetworkAbort(traceId); + doNetworkReset(traceId); + + delegate.cleanupApplication(traceId, EMPTY_OCTETS); + } + + private void cleanupDecodeSlotIfNecessary() + { + if (decodeSlot != NO_SLOT) + { + decodePool.release(decodeSlot); + decodeSlot = NO_SLOT; + decodeSlotOffset = 0; + decodeSlotReserved = 0; + } + } + + private void cleanupEncodeSlotIfNecessary() + { + if (encodeSlot != NO_SLOT) + { + encodePool.release(encodeSlot); + encodeSlot = NO_SLOT; + encodeSlotOffset = 0; + encodeSlotTraceId = 0; + } + } + } + + private final class DescribeClient extends KafkaSaslClient + { + private final LongLongConsumer encodeSaslHandshakeRequest = this::doEncodeSaslHandshakeRequest; + private final LongLongConsumer encodeSaslAuthenticateRequest = this::doEncodeSaslAuthenticateRequest; + private final LongLongConsumer encodeDescribeRequest = this::doEncodeDescribeRequest; + + private MessageConsumer network; + private final Map configs; + private final KafkaGroupStream delegate; + + private int state; + private long authorization; + + private long initialSeq; + private long initialAck; + private int initialMin; + private int initialMax; + private int initialPad; + private long initialBudgetId = NO_BUDGET_ID; + private long initialDebIndex = NO_CREDITOR_INDEX; + + private long replySeq; + private long replyAck; + private int replyMax; + + private int encodeSlot = NO_SLOT; + private int encodeSlotOffset; + private long encodeSlotTraceId; + + private int decodeSlot = NO_SLOT; + private int decodeSlotOffset; + private int decodeSlotReserved; + + private int nextResponseId; + + private KafkaDescribeClientDecoder decoder; + private LongLongConsumer encoder; + private BudgetDebitor initialDeb; + + DescribeClient( + long originId, + long routedId, + KafkaSaslConfig sasl, + KafkaGroupStream delegate) + { + super(sasl, originId, routedId); + this.configs = new LinkedHashMap<>(); + this.delegate = delegate; + + this.encoder = sasl != null ? encodeSaslHandshakeRequest : encodeDescribeRequest; + this.decoder = decodeReject; + + this.configs.put(GROUP_MIN_SESSION_TIMEOUT, null); + this.configs.put(GROUP_MAX_SESSION_TIMEOUT, null); + } + + public void onDecodeResource( + long traceId, + long authorization, + int errorCode, + String resource) + { + switch (errorCode) + { + case ERROR_NONE: + assert resource.equals(delegate.nodeId); + break; + default: + final KafkaResetExFW resetEx = kafkaResetExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .error(errorCode) + .build(); + delegate.cleanupApplication(traceId, resetEx); + doNetworkEnd(traceId, authorization); + break; + } + } + + private void onNetwork( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onNetworkBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onNetworkData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onNetworkEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onNetworkAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onNetworkReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onNetworkWindow(window); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onNetworkSignal(signal); + break; + default: + break; + } + } + + private void onNetworkBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + authorization = begin.authorization(); + state = KafkaState.openingReply(state); + + doNetworkWindow(traceId, 0L, 0, 0, decodePool.slotCapacity()); + } + + private void onNetworkData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long budgetId = data.budgetId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + data.reserved(); + authorization = data.authorization(); + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + cleanupNetwork(traceId); + } + else + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + cleanupNetwork(traceId); + } + else + { + final OctetsFW payload = data.payload(); + int reserved = data.reserved(); + int offset = payload.offset(); + int limit = payload.limit(); + + final MutableDirectBuffer buffer = decodePool.buffer(decodeSlot); + buffer.putBytes(decodeSlotOffset, payload.buffer(), offset, limit - offset); + decodeSlotOffset += limit - offset; + decodeSlotReserved += reserved; + + offset = 0; + limit = decodeSlotOffset; + reserved = decodeSlotReserved; + + decodeNetwork(traceId, authorization, budgetId, reserved, buffer, offset, limit); + } + } + } + + private void onNetworkEnd( + EndFW end) + { + state = KafkaState.closedReply(state); + + cleanupDecodeSlotIfNecessary(); + } + + private void onNetworkAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedReply(state); + + cleanupNetwork(traceId); + } + + private void onNetworkReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + cleanupNetwork(traceId); + } + + private void onNetworkWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int minimum = window.minimum(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= initialSeq; + assert acknowledge >= initialAck; + assert maximum + acknowledge >= initialMax + initialAck; + + this.initialAck = acknowledge; + this.initialMax = maximum; + this.initialPad = padding; + this.initialMin = minimum; + this.initialBudgetId = budgetId; + + assert initialAck <= initialSeq; + + this.authorization = window.authorization(); + + state = KafkaState.openedInitial(state); + + if (initialBudgetId != NO_BUDGET_ID && initialDebIndex == NO_DEBITOR_INDEX) + { + initialDeb = supplyDebitor.apply(initialBudgetId); + initialDebIndex = initialDeb.acquire(initialBudgetId, initialId, this::doNetworkDataIfNecessary); + assert initialDebIndex != NO_DEBITOR_INDEX; + } + + doNetworkDataIfNecessary(budgetId); + + doEncodeRequestIfNecessary(traceId, budgetId); + } + + private void doNetworkDataIfNecessary( + long budgetId) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer buffer = encodePool.buffer(encodeSlot); + final int limit = encodeSlotOffset; + + encodeNetwork(encodeSlotTraceId, authorization, budgetId, buffer, 0, limit); + } + } + + private void onNetworkSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final int signalId = signal.signalId(); + + if (signalId == SIGNAL_NEXT_REQUEST) + { + doEncodeRequestIfNecessary(traceId, initialBudgetId); + } + } + + private void doNetworkBegin( + long traceId, + long authorization, + long affinity) + { + if (KafkaState.closed(state)) + { + replyAck = 0; + replySeq = 0; + state = 0; + } + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + state = KafkaState.openingInitial(state); + + network = newStream(this::onNetwork, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, EMPTY_EXTENSION); + } + + @Override + protected void doNetworkData( + long traceId, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(encodeSlotOffset, buffer, offset, limit - offset); + encodeSlotOffset += limit - offset; + encodeSlotTraceId = traceId; + + buffer = encodeBuffer; + offset = 0; + limit = encodeSlotOffset; + } + + encodeNetwork(traceId, authorization, budgetId, buffer, offset, limit); + } + + private void doNetworkEnd( + long traceId, + long authorization) + { + state = KafkaState.closedInitial(state); + + cleanupEncodeSlotIfNecessary(); + + doEnd(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + } + + private void doNetworkAbort( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doAbort(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + state = KafkaState.closedInitial(state); + } + + cleanupEncodeSlotIfNecessary(); + } + + private void doNetworkReset( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doReset(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + state = KafkaState.closedReply(state); + } + + cleanupDecodeSlotIfNecessary(); + } + + private void doNetworkWindow( + long traceId, + long budgetId, + int minReplyNoAck, + int minReplyPad, + int minReplyMax) + { + final long newReplyAck = Math.max(replySeq - minReplyNoAck, replyAck); + + if (newReplyAck > replyAck || minReplyMax > replyMax || !KafkaState.replyOpened(state)) + { + replyAck = newReplyAck; + assert replyAck <= replySeq; + + replyMax = minReplyMax; + + state = KafkaState.openedReply(state); + + doWindow(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, minReplyPad); + } + } + + private void doEncodeRequestIfNecessary( + long traceId, + long budgetId) + { + if (nextRequestId == nextResponseId) + { + encoder.accept(traceId, budgetId); + } + } + + private void doEncodeDescribeRequest( + long traceId, + long budgetId) + { + if (KafkaConfiguration.DEBUG) + { + System.out.format("[client] %s DESCRIBE\n", delegate.nodeId); + } + + final MutableDirectBuffer encodeBuffer = writeBuffer; + final int encodeOffset = DataFW.FIELD_OFFSET_PAYLOAD; + final int encodeLimit = encodeBuffer.capacity(); + + int encodeProgress = encodeOffset; + + final RequestHeaderFW requestHeader = requestHeaderRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .length(0) + .apiKey(DESCRIBE_CONFIGS_API_KEY) + .apiVersion(DESCRIBE_CONFIGS_API_VERSION) + .correlationId(0) + .clientId((String) null) + .build(); + + encodeProgress = requestHeader.limit(); + + final DescribeConfigsRequestFW describeConfigsRequest = + describeConfigsRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .resourceCount(1) + .build(); + + encodeProgress = describeConfigsRequest.limit(); + + final ResourceRequestFW resourceRequest = resourceRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .type(RESOURCE_TYPE_BROKER) + .name(delegate.nodeId) + .configNamesCount(configs.size()) + .build(); + + encodeProgress = resourceRequest.limit(); + + for (String config : configs.keySet()) + { + final String16FW configName = configNameRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .set(config, UTF_8) + .build(); + + encodeProgress = configName.limit(); + } + + final int requestId = nextRequestId++; + final int requestSize = encodeProgress - encodeOffset - RequestHeaderFW.FIELD_OFFSET_API_KEY; + + requestHeaderRW.wrap(encodeBuffer, requestHeader.offset(), requestHeader.limit()) + .length(requestSize) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId().asString()) + .build(); + + doNetworkData(traceId, budgetId, encodeBuffer, encodeOffset, encodeProgress); + + decoder = decodeDescribeResponse; + } + + private void encodeNetwork( + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + final int length = limit - offset; + final int lengthMin = Math.min(length, 1024); + final int initialBudget = Math.max(initialMax - (int)(initialSeq - initialAck), 0); + final int reservedMax = Math.max(Math.min(length + initialPad, initialBudget), initialMin); + final int reservedMin = Math.max(Math.min(lengthMin + initialPad, reservedMax), initialMin); + + int reserved = reservedMax; + + flush: + if (reserved > 0) + { + + boolean claimed = false; + + if (initialDebIndex != NO_DEBITOR_INDEX) + { + final int lengthMax = Math.min(reserved - initialPad, length); + final int deferredMax = length - lengthMax; + reserved = initialDeb.claim(traceId, initialDebIndex, initialId, reservedMin, reserved, deferredMax); + claimed = reserved > 0; + } + + if (reserved < initialPad || reserved == initialPad && length > 0) + { + break flush; + } + + doData(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, buffer, offset, length, EMPTY_EXTENSION); + + initialSeq += reserved; + + assert initialAck <= initialSeq; + } + + final int flushed = Math.max(reserved - initialPad, 0); + final int remaining = length - flushed; + if (remaining > 0) + { + if (encodeSlot == NO_SLOT) + { + encodeSlot = encodePool.acquire(initialId); + } + + if (encodeSlot == NO_SLOT) + { + cleanupNetwork(traceId); + } + else + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(0, buffer, offset + flushed, remaining); + encodeSlotOffset = remaining; + } + } + else + { + cleanupEncodeSlotIfNecessary(); + } + } + + private void decodeNetwork( + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int limit) + { + KafkaDescribeClientDecoder previous = null; + int progress = offset; + while (progress <= limit && previous != decoder) + { + previous = decoder; + progress = decoder.decode(this, traceId, authorization, budgetId, reserved, buffer, offset, progress, limit); + } + + if (progress < limit) + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + cleanupNetwork(traceId); + } + else + { + final MutableDirectBuffer decodeBuffer = decodePool.buffer(decodeSlot); + decodeBuffer.putBytes(0, buffer, progress, limit - progress); + decodeSlotOffset = limit - progress; + decodeSlotReserved = (limit - progress) * reserved / (limit - offset); + } + + doNetworkWindow(traceId, budgetId, decodeSlotOffset, 0, replyMax); + } + else + { + cleanupDecodeSlotIfNecessary(); + + if (reserved > 0) + { + doNetworkWindow(traceId, budgetId, 0, 0, replyMax); + } + } + } + + @Override + protected void doDecodeSaslHandshakeResponse( + long traceId) + { + decoder = decodeSaslHandshakeResponse; + } + + @Override + protected void doDecodeSaslHandshake( + long traceId) + { + decoder = decodeSaslHandshake; + } + + @Override + protected void doDecodeSaslHandshakeMechanisms( + long traceId) + { + decoder = decodeSaslHandshakeMechanisms; + } + + @Override + protected void doDecodeSaslHandshakeMechansim( + long traceId) + { + decoder = decodeSaslHandshakeMechanism; + } + + @Override + protected void doDecodeSaslAuthenticateResponse( + long traceId) + { + decoder = decodeSaslAuthenticateResponse; + } + + @Override + protected void doDecodeSaslAuthenticate( + long traceId) + { + decoder = decodeSaslAuthenticate; + } + + @Override + protected void onDecodeSaslHandshakeResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + encoder = encodeSaslAuthenticateRequest; + decoder = decodeSaslAuthenticateResponse; + break; + default: + delegate.cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslAuthenticateResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + encoder = encodeDescribeRequest; + decoder = decodeDescribeResponse; + break; + default: + delegate.cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslResponse( + long traceId) + { + nextResponseId++; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onDecodeDescribeResponse( + long traceId, + Map newConfigs) + { + nextResponseId++; + + int timeoutMin = Integer.valueOf(newConfigs.get(GROUP_MIN_SESSION_TIMEOUT)).intValue(); + int timeoutMax = Integer.valueOf(newConfigs.get(GROUP_MAX_SESSION_TIMEOUT)).intValue(); + if (delegate.timeout < timeoutMin) + { + delegate.timeout = timeoutMin; + } + else if (delegate.timeout > timeoutMax) + { + delegate.timeout = timeoutMax; + } + + delegate.coordinatorClient.doNetworkBeginIfNecessary(traceId, authorization, 0); + + cleanupNetwork(traceId); + } + + private void cleanupNetwork( + long traceId) + { + doNetworkAbort(traceId); + doNetworkReset(traceId); + } + + private void cleanupDecodeSlotIfNecessary() + { + if (decodeSlot != NO_SLOT) + { + decodePool.release(decodeSlot); + decodeSlot = NO_SLOT; + decodeSlotOffset = 0; + decodeSlotReserved = 0; + } + } + + private void cleanupEncodeSlotIfNecessary() + { + if (encodeSlot != NO_SLOT) + { + encodePool.release(encodeSlot); + encodeSlot = NO_SLOT; + encodeSlotOffset = 0; + encodeSlotTraceId = 0; + } + } + } + + private final class CoordinatorClient extends KafkaSaslClient + { + private final LongLongConsumer encodeSaslHandshakeRequest = this::doEncodeSaslHandshakeRequest; + private final LongLongConsumer encodeSaslAuthenticateRequest = this::doEncodeSaslAuthenticateRequest; + private final LongLongConsumer encodeJoinGroupRequest = this::doEncodeJoinGroupRequest; + private final LongLongConsumer encodeSyncGroupRequest = this::doEncodeSyncGroupRequest; + private final LongLongConsumer encodeHeartbeatRequest = this::doEncodeHeartbeatRequest; + private final LongLongConsumer encodeLeaveGroupRequest = this::doEncodeLeaveGroupRequest; + private final List members; + private final KafkaGroupStream delegate; + + private MessageConsumer network; + + private int state; + private long authorization; + + private long initialSeq; + private long initialAck; + private int initialMin; + private int initialMax; + private int initialPad; + private long initialBudgetId = NO_BUDGET_ID; + private long initialDebIndex = NO_CREDITOR_INDEX; + + private long replySeq; + private long replyAck; + private int replyMax; + + private int encodeSlot = NO_SLOT; + private int encodeSlotOffset; + private long encodeSlotTraceId; + + private int decodeSlot = NO_SLOT; + private int decodeSlotOffset; + private int decodeSlotReserved; + + private int nextResponseId; + private long heartbeatRequestId = NO_CANCEL_ID; + + + private int generationId; + private int nextJoinGroupRequestId; + private int nextJoinGroupResponseId; + private KafkaGroupCoordinatorClientDecoder decoder; + private LongLongConsumer encoder; + private OctetsFW assignment = EMPTY_OCTETS; + private BudgetDebitor initialDeb; + + CoordinatorClient( + long originId, + long routedId, + KafkaSaslConfig sasl, + KafkaGroupStream delegate) + { + super(sasl, originId, routedId); + + this.encoder = sasl != null ? encodeSaslHandshakeRequest : encodeJoinGroupRequest; + this.delegate = delegate; + this.decoder = decodeCoordinatorReject; + this.members = new ArrayList<>(); + } + + private void onNetwork( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onNetworkBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onNetworkData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onNetworkEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onNetworkAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onNetworkReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onNetworkWindow(window); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onNetworkSignal(signal); + break; + default: + break; + } + } + + private void onNetworkBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + authorization = begin.authorization(); + state = KafkaState.openingReply(state); + + doNetworkWindow(traceId, 0L, 0, 0, decodePool.slotCapacity()); + } + + private void onNetworkData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long budgetId = data.budgetId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + data.reserved(); + authorization = data.authorization(); + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + onError(traceId); + } + else + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + onError(traceId); + } + else + { + final OctetsFW payload = data.payload(); + int reserved = data.reserved(); + int offset = payload.offset(); + int limit = payload.limit(); + + final MutableDirectBuffer buffer = decodePool.buffer(decodeSlot); + buffer.putBytes(decodeSlotOffset, payload.buffer(), offset, limit - offset); + decodeSlotOffset += limit - offset; + decodeSlotReserved += reserved; + + offset = 0; + limit = decodeSlotOffset; + reserved = decodeSlotReserved; + + decodeNetwork(traceId, authorization, budgetId, reserved, buffer, offset, limit); + } + } + } + + private void onNetworkEnd( + EndFW end) + { + final long traceId = end.traceId(); + + state = KafkaState.closedReply(state); + + cleanupDecodeSlotIfNecessary(); + + if (!delegate.isApplicationReplyOpen()) + { + onError(traceId); + } + } + + private void onNetworkAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedReply(state); + + onError(traceId); + } + + private void onNetworkReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + onError(traceId); + } + + private void onNetworkWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int minimum = window.minimum(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= initialSeq; + assert acknowledge >= initialAck; + assert maximum + acknowledge >= initialMax + initialAck; + + this.initialAck = acknowledge; + this.initialMax = maximum; + this.initialPad = padding; + this.initialMin = minimum; + this.initialBudgetId = budgetId; + + assert initialAck <= initialSeq; + + this.authorization = window.authorization(); + + state = KafkaState.openedInitial(state); + + if (initialBudgetId != NO_BUDGET_ID && initialDebIndex == NO_DEBITOR_INDEX) + { + initialDeb = supplyDebitor.apply(initialBudgetId); + initialDebIndex = initialDeb.acquire(initialBudgetId, initialId, this::doNetworkDataIfNecessary); + assert initialDebIndex != NO_DEBITOR_INDEX; + } + + doNetworkDataIfNecessary(budgetId); + + doEncodeRequestIfNecessary(traceId, budgetId); + } + + private void doNetworkDataIfNecessary(long budgetId) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer buffer = encodePool.buffer(encodeSlot); + final int limit = encodeSlotOffset; + + encodeNetwork(encodeSlotTraceId, authorization, budgetId, buffer, 0, limit); + } + } + + private void onNetworkSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final int signalId = signal.signalId(); + + if (signalId == SIGNAL_NEXT_REQUEST) + { + doEncodeRequestIfNecessary(traceId, initialBudgetId); + } + } + + private void doNetworkBeginIfNecessary( + long traceId, + long authorization, + long affinity) + { + if (KafkaState.closed(state)) + { + replyAck = 0; + replySeq = 0; + state = 0; + nextJoinGroupRequestId = 0; + nextJoinGroupResponseId = 0; + nextRequestId = 0; + nextResponseId = 0; + } + + if (!KafkaState.initialOpening(state)) + { + doNetworkBegin(traceId, authorization, affinity); + } + } + + private void doNetworkBegin( + long traceId, + long authorization, + long affinity) + { + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + nextJoinGroupRequestId++; + + state = KafkaState.openingInitial(state); + + Consumer extension = e -> e.set((b, o, l) -> proxyBeginExRW.wrap(b, o, l) + .typeId(proxyTypeId) + .address(a -> a.inet(i -> i.protocol(p -> p.set(STREAM)) + .source("0.0.0.0") + .destination(delegate.host) + .sourcePort(0) + .destinationPort(delegate.port))) + .build() + .sizeof()); + + network = newStream(this::onNetwork, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, extension); + } + + @Override + protected void doNetworkData( + long traceId, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(encodeSlotOffset, buffer, offset, limit - offset); + encodeSlotOffset += limit - offset; + encodeSlotTraceId = traceId; + + buffer = encodeBuffer; + offset = 0; + limit = encodeSlotOffset; + } + + encodeNetwork(traceId, authorization, budgetId, buffer, offset, limit); + } + + private void doNetworkEnd( + long traceId, + long authorization) + { + if (KafkaState.initialOpening(state) && !KafkaState.initialClosed(state)) + { + state = KafkaState.closedInitial(state); + + doEnd(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + } + + cleanupEncodeSlotIfNecessary(); + + } + + private void doNetworkAbort( + long traceId) + { + if (KafkaState.initialOpened(state) && + !KafkaState.initialClosed(state)) + { + doAbort(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + state = KafkaState.closedInitial(state); + } + + cleanupEncodeSlotIfNecessary(); + } + + private void doNetworkReset( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doReset(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + state = KafkaState.closedReply(state); + } + + cleanupDecodeSlotIfNecessary(); + } + + private void doNetworkWindow( + long traceId, + long budgetId, + int minReplyNoAck, + int minReplyPad, + int minReplyMax) + { + final long newReplyAck = Math.max(replySeq - minReplyNoAck, replyAck); + + if (newReplyAck > replyAck || minReplyMax > replyMax || !KafkaState.replyOpened(state)) + { + replyAck = newReplyAck; + assert replyAck <= replySeq; + + replyMax = minReplyMax; + + state = KafkaState.openedReply(state); + + doWindow(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, minReplyPad); + } + } + + private void doEncodeRequestIfNecessary( + long traceId, + long budgetId) + { + if (nextRequestId == nextResponseId) + { + encoder.accept(traceId, budgetId); + } + } + + private void doEncodeJoinGroupRequest( + long traceId, + long budgetId) + { + final MutableDirectBuffer encodeBuffer = writeBuffer; + final int encodeOffset = DataFW.FIELD_OFFSET_PAYLOAD; + final int encodeLimit = encodeBuffer.capacity(); + + int encodeProgress = encodeOffset; + + final RequestHeaderFW requestHeader = requestHeaderRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .length(0) + .apiKey(JOIN_GROUP_API_KEY) + .apiVersion(JOIN_GROUP_VERSION) + .correlationId(0) + .clientId(clientId) + .build(); + + encodeProgress = requestHeader.limit(); + + final String memberId = delegate.groupMembership.memberIds.getOrDefault(delegate.groupId, UNKNOWN_MEMBER_ID); + + final JoinGroupRequestFW joinGroupRequest = + joinGroupRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .groupId(delegate.groupId) + .sessionTimeoutMillis(delegate.timeout) + .rebalanceTimeoutMillis((int) rebalanceTimeout.toMillis()) + .memberId(memberId) + .groupInstanceId(delegate.groupMembership.instanceId) + .protocolType("consumer") + .protocolCount(1) + .build(); + + encodeProgress = joinGroupRequest.limit(); + + final int metadataLimit = delegate.topicMetadataLimit > 0 ? doGenerateSubscriptionMetadata() : + doGenerateEmptySubscriptionMetadata(); + + final ProtocolMetadataFW protocolMetadata = + protocolMetadataRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .name(delegate.protocol) + .metadata(extBuffer, 0, metadataLimit) + .build(); + + encodeProgress = protocolMetadata.limit(); + + final int requestId = nextRequestId++; + final int requestSize = encodeProgress - encodeOffset - RequestHeaderFW.FIELD_OFFSET_API_KEY; + + requestHeaderRW.wrap(encodeBuffer, requestHeader.offset(), requestHeader.limit()) + .length(requestSize) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId().asString()) + .build(); + + doNetworkData(traceId, budgetId, encodeBuffer, encodeOffset, encodeProgress); + + decoder = decodeJoinGroupResponse; + + delegate.doApplicationBeginIfNecessary(traceId, authorization); + } + + private int doGenerateSubscriptionMetadata() + { + final MutableDirectBuffer encodeBuffer = extBuffer; + final int encodeOffset = 0; + final int encodeLimit = encodeBuffer.capacity(); + + final MutableInteger encodeProgress = new MutableInteger(encodeOffset); + + KafkaGroupMemberMetadataFW memberMetadata = kafkaMemberMetadataRO + .wrap(delegate.metadataBuffer, 0, delegate.topicMetadataLimit); + + ConsumerSubscriptionMetadataFW metadata = groupSubscriptionMetadataRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .version(METADATA_LOWEST_VERSION) + .metadataTopicCount(memberMetadata.topics().fieldCount()) + .build(); + + encodeProgress.set(metadata.limit()); + + memberMetadata.topics().forEach(t -> + { + ConsumerMetadataTopicFW metadataTopic = metadataTopicRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .name(t.topic()) + .build(); + encodeProgress.set(metadataTopic.limit()); + }); + + memberMetadata.topics().forEach(t -> + { + final ConsumerSubscriptionUserdataFW userdata = subscriptionUserdataRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .userdata(delegate.metadataBuffer, 0, delegate.topicMetadataLimit) + .ownedPartitions(0) + .build(); + + encodeProgress.set(userdata.limit()); + }); + + return encodeProgress.get(); + } + + private int doGenerateEmptySubscriptionMetadata() + { + final MutableDirectBuffer encodeBuffer = extBuffer; + final int encodeOffset = 0; + final int encodeLimit = encodeBuffer.capacity(); + + final MutableInteger encodeProgress = new MutableInteger(encodeOffset); + + ConsumerSubscriptionMetadataFW metadata = groupSubscriptionMetadataRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .version(METADATA_LOWEST_VERSION) + .metadataTopicCount(0) + .build(); + + encodeProgress.set(metadata.limit()); + + final ConsumerSubscriptionUserdataFW userdata = subscriptionUserdataRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .userdata(delegate.metadataBuffer, 0, delegate.topicMetadataLimit) + .ownedPartitions(0) + .build(); + + encodeProgress.set(userdata.limit()); + + return encodeProgress.get(); + } + + private int doGenerateAssignmentMetadata( + Array32FW topicPartitions, + int progressOffset) + { + final MutableDirectBuffer encodeBuffer = extBuffer; + final int encodeOffset = progressOffset; + final int encodeLimit = encodeBuffer.capacity(); + + final MutableInteger encodeProgress = new MutableInteger(encodeOffset); + + ConsumerAssignmentMetadataFW metadata = assignmentMetadataRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .version(METADATA_LOWEST_VERSION) + .metadataTopicCount(topicPartitions.fieldCount()) + .build(); + + encodeProgress.set(metadata.limit()); + + topicPartitions.forEach(t -> + { + final Array32FW partitions = t.partitions(); + + ConsumerTopicPartitionFW topicPartition = topicPartitionRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .topic(t.topic()) + .partitionCount(partitions.fieldCount()) + .build(); + encodeProgress.set(topicPartition.limit()); + + partitions.forEach(p -> + { + ConsumerPartitionFW partition = partitionRW.wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .partitionId(p.partitionId()) + .build(); + encodeProgress.set(partition.limit()); + }); + + Array32FW assignmentUserdata = t.userdata(); + final ConsumerAssignmentUserdataFW userdata = assignmentUserdataRW + .wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .userdata(assignmentUserdata.buffer(), assignmentUserdata.offset(), assignmentUserdata.sizeof()) + .build(); + + encodeProgress.set(userdata.limit()); + + }); + + return encodeProgress.get(); + } + + private void doEncodeSyncGroupRequest( + long traceId, + long budgetId) + { + final MutableDirectBuffer encodeBuffer = writeBuffer; + final int encodeOffset = DataFW.FIELD_OFFSET_PAYLOAD; + final int encodeLimit = encodeBuffer.capacity(); + + MutableInteger encodeProgress = new MutableInteger(encodeOffset); + + final RequestHeaderFW requestHeader = requestHeaderRW.wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .length(0) + .apiKey(SYNC_GROUP_API_KEY) + .apiVersion(SYNC_GROUP_VERSION) + .correlationId(0) + .clientId(clientId) + .build(); + + encodeProgress.set(requestHeader.limit()); + + final String memberId = delegate.groupMembership.memberIds.get(delegate.groupId); + + final SyncGroupRequestFW syncGroupRequest = + syncGroupRequestRW.wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .groupId(delegate.groupId) + .generatedId(generationId) + .memberId(memberId) + .groupInstanceId(delegate.groupMembership.instanceId) + .assignmentCount(members.size()) + .build(); + + encodeProgress.set(syncGroupRequest.limit()); + + if (assignment.sizeof() > 0) + { + Array32FW assignments = memberAssignmentRO + .wrap(assignment.buffer(), assignment.offset(), assignment.limit()); + + MutableInteger progressOffset = new MutableInteger(); + assignments.forEach(a -> + { + Array32FW topicPartitions = a.assignments(); + + int newProgressOffset = doGenerateAssignmentMetadata(topicPartitions, progressOffset.get()); + final AssignmentFW memberAssignment = + assignmentRW.wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .memberId(a.memberId()) + .value(extBuffer, progressOffset.get(), newProgressOffset) + .build(); + + encodeProgress.set(memberAssignment.limit()); + progressOffset.set(newProgressOffset); + }); + } + else + { + members.forEach(m -> + { + final AssignmentFW groupAssignment = + assignmentRW.wrap(encodeBuffer, encodeProgress.get(), encodeLimit) + .memberId(m.memberId) + .value(EMPTY_OCTETS) + .build(); + + encodeProgress.set(groupAssignment.limit()); + }); + } + + + final int requestId = nextRequestId++; + final int requestSize = encodeProgress.get() - encodeOffset - RequestHeaderFW.FIELD_OFFSET_API_KEY; + + requestHeaderRW.wrap(encodeBuffer, requestHeader.offset(), requestHeader.limit()) + .length(requestSize) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId().asString()) + .build(); + + doNetworkData(traceId, budgetId, encodeBuffer, encodeOffset, encodeProgress.get()); + + decoder = decodeSyncGroupResponse; + } + + private void doEncodeHeartbeatRequest( + long traceId, + long budgetId) + { + final MutableDirectBuffer encodeBuffer = writeBuffer; + final int encodeOffset = DataFW.FIELD_OFFSET_PAYLOAD; + final int encodeLimit = encodeBuffer.capacity(); + + int encodeProgress = encodeOffset; + + final RequestHeaderFW requestHeader = requestHeaderRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .length(0) + .apiKey(HEARTBEAT_API_KEY) + .apiVersion(HEARTBEAT_VERSION) + .correlationId(0) + .clientId(clientId) + .build(); + + encodeProgress = requestHeader.limit(); + + final String memberId = delegate.groupMembership.memberIds.get(delegate.groupId); + + final HeartbeatRequestFW heartbeatRequest = + heartbeatRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .groupId(delegate.groupId) + .generatedId(generationId) + .memberId(memberId) + .groupInstanceId(delegate.groupMembership.instanceId) + .build(); + + encodeProgress = heartbeatRequest.limit(); + + final int requestId = nextRequestId++; + final int requestSize = encodeProgress - encodeOffset - RequestHeaderFW.FIELD_OFFSET_API_KEY; + + requestHeaderRW.wrap(encodeBuffer, requestHeader.offset(), requestHeader.limit()) + .length(requestSize) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId().asString()) + .build(); + + doNetworkData(traceId, budgetId, encodeBuffer, encodeOffset, encodeProgress); + + decoder = decodeHeartbeatResponse; + } + + private void doEncodeLeaveGroupRequest( + long traceId, + long budgetId) + { + final MutableDirectBuffer encodeBuffer = writeBuffer; + final int encodeOffset = DataFW.FIELD_OFFSET_PAYLOAD; + final int encodeLimit = encodeBuffer.capacity(); + + int encodeProgress = encodeOffset; + + final RequestHeaderFW requestHeader = requestHeaderRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .length(0) + .apiKey(LEAVE_GROUP_API_KEY) + .apiVersion(LEAVE_GROUP_VERSION) + .correlationId(0) + .clientId(clientId) + .build(); + + encodeProgress = requestHeader.limit(); + + final LeaveGroupRequestFW leaveGroupRequest = + leaveGroupRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .groupId(delegate.groupId) + .memberCount(1) + .build(); + + encodeProgress = leaveGroupRequest.limit(); + + final String memberId = delegate.groupMembership.memberIds.get(delegate.groupId); + + final LeaveMemberFW leaveMember = leaveMemberRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .memberId(memberId) + .groupInstanceId(delegate.groupMembership.instanceId) + .build(); + + encodeProgress = leaveMember.limit(); + + final int requestId = nextRequestId++; + final int requestSize = encodeProgress - encodeOffset - RequestHeaderFW.FIELD_OFFSET_API_KEY; + + requestHeaderRW.wrap(encodeBuffer, requestHeader.offset(), requestHeader.limit()) + .length(requestSize) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId().asString()) + .build(); + + doNetworkData(traceId, budgetId, encodeBuffer, encodeOffset, encodeProgress); + + decoder = decodeLeaveGroupResponse; + } + + private void doSyncRequest( + long traceId, + long budgetId, + OctetsFW assignment) + { + this.assignment = assignment; + + encoder = encodeSyncGroupRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void doJoinGroupRequest( + long traceId) + { + if (heartbeatRequestId != NO_CANCEL_ID) + { + signaler.cancel(heartbeatRequestId); + heartbeatRequestId = NO_CANCEL_ID; + } + + if (nextJoinGroupRequestId != 0 && + nextJoinGroupRequestId == nextJoinGroupResponseId) + { + encoder = encodeJoinGroupRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + nextJoinGroupRequestId++; + } + + private void doHeartbeat( + long traceId) + { + if (encoder != encodeJoinGroupRequest) + { + if (heartbeatRequestId != NO_CANCEL_ID) + { + signaler.cancel(heartbeatRequestId); + heartbeatRequestId = NO_CANCEL_ID; + } + + encoder = encodeHeartbeatRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + } + + private void doLeaveGroupRequest( + long traceId) + { + if (heartbeatRequestId != NO_CANCEL_ID) + { + signaler.cancel(heartbeatRequestId); + heartbeatRequestId = NO_CANCEL_ID; + } + + encoder = encodeLeaveGroupRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void encodeNetwork( + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + final int length = limit - offset; + final int lengthMin = Math.min(length, 1024); + final int initialBudget = Math.max(initialMax - (int)(initialSeq - initialAck), 0); + final int reservedMax = Math.max(Math.min(length + initialPad, initialBudget), initialMin); + final int reservedMin = Math.max(Math.min(lengthMin + initialPad, reservedMax), initialMin); + + int reserved = reservedMax; + + flush: + if (reserved > 0) + { + + boolean claimed = false; + + if (initialDebIndex != NO_DEBITOR_INDEX) + { + final int lengthMax = Math.min(reserved - initialPad, length); + final int deferredMax = length - lengthMax; + reserved = initialDeb.claim(traceId, initialDebIndex, initialId, reservedMin, reserved, deferredMax); + claimed = reserved > 0; + } + + if (reserved < initialPad || reserved == initialPad && length > 0) + { + break flush; + } + + doData(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, buffer, offset, length, EMPTY_EXTENSION); + + initialSeq += reserved; + + assert initialAck <= initialSeq; + } + + final int flushed = Math.max(reserved - initialPad, 0); + final int remaining = length - flushed; + if (remaining > 0) + { + if (encodeSlot == NO_SLOT) + { + encodeSlot = encodePool.acquire(initialId); + } + + if (encodeSlot == NO_SLOT) + { + onError(traceId); + } + else + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(0, buffer, offset + flushed, remaining); + encodeSlotOffset = remaining; + } + } + else + { + cleanupEncodeSlotIfNecessary(); + } + } + + private void decodeNetwork( + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int limit) + { + KafkaGroupCoordinatorClientDecoder previous = null; + int progress = offset; + while (progress <= limit && previous != decoder) + { + previous = decoder; + progress = decoder.decode(this, traceId, authorization, budgetId, reserved, buffer, offset, progress, limit); + } + + if (progress < limit) + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + onError(traceId); + } + else + { + final MutableDirectBuffer decodeBuffer = decodePool.buffer(decodeSlot); + decodeBuffer.putBytes(0, buffer, progress, limit - progress); + decodeSlotOffset = limit - progress; + decodeSlotReserved = (limit - progress) * reserved / (limit - offset); + } + + doNetworkWindow(traceId, budgetId, decodeSlotOffset, 0, replyMax); + } + else + { + cleanupDecodeSlotIfNecessary(); + + if (reserved > 0) + { + doNetworkWindow(traceId, budgetId, 0, 0, replyMax); + } + } + } + + @Override + protected void doDecodeSaslHandshakeResponse( + long traceId) + { + decoder = decodeCoordinatorSaslHandshakeResponse; + } + + @Override + protected void doDecodeSaslHandshake( + long traceId) + { + decoder = decodeCoordinatorSaslHandshake; + } + + @Override + protected void doDecodeSaslHandshakeMechanisms( + long traceId) + { + decoder = decodeCoordinatorSaslHandshakeMechanisms; + } + + @Override + protected void doDecodeSaslHandshakeMechansim( + long traceId) + { + decoder = decodeCoordinatorSaslHandshakeMechanism; + } + + @Override + protected void doDecodeSaslAuthenticateResponse( + long traceId) + { + decoder = decodeCoordinatorSaslAuthenticateResponse; + } + + @Override + protected void doDecodeSaslAuthenticate( + long traceId) + { + decoder = decodeCoordinatorSaslAuthenticate; + } + + @Override + protected void onDecodeSaslHandshakeResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + encoder = encodeSaslAuthenticateRequest; + decoder = decodeCoordinatorSaslAuthenticateResponse; + break; + default: + delegate.cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslAuthenticateResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + encoder = encodeJoinGroupRequest; + decoder = decodeJoinGroupResponse; + break; + default: + delegate.cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslResponse( + long traceId) + { + nextResponseId++; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onNotCoordinatorError( + long traceId, + long authorization) + { + nextResponseId++; + + cleanupNetwork(traceId, authorization); + + delegate.onNotCoordinatorError(traceId, authorization); + } + + private void onJoinGroupMemberIdError( + long traceId, + long authorization, + String memberId) + { + nextResponseId++; + + delegate.groupMembership.memberIds.put(delegate.groupId, memberId); + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onJoinGroupResponse( + long traceId, + long authorization, + String leaderId, + String memberId) + { + nextResponseId++; + nextJoinGroupResponseId++; + + delegate.groupMembership.memberIds.put(delegate.groupId, memberId); + + if (nextJoinGroupRequestId == nextJoinGroupResponseId) + { + delegate.doApplicationFlush(traceId, authorization, + ex -> ex.set((b, o, l) -> kafkaFlushExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .group(g -> g.leaderId(leaderId) + .memberId(memberId) + .members(gm -> members.forEach(m -> + { + OctetsFW metadata = m.metadata; + DirectBuffer buffer = metadata.value(); + final int limit = metadata.sizeof(); + + int progress = 0; + + ConsumerSubscriptionMetadataFW newGroupMetadata = subscriptionMetadataRO + .wrap(buffer, 0, metadata.sizeof()); + progress = newGroupMetadata.limit(); + + for (int i = 0; i < newGroupMetadata.metadataTopicCount(); i++) + { + ConsumerMetadataTopicFW topic = metadataTopicRO.wrap(buffer, progress, limit); + progress = topic.limit(); + } + + ConsumerSubscriptionUserdataFW userdata = subscriptionUserdataRO.wrap(buffer, progress, limit); + + gm.item(i -> + { + KafkaGroupMemberFW.Builder builder = i.id(m.memberId); + OctetsFW newUserdata = userdata.userdata(); + if (newUserdata.sizeof() > 0) + { + builder.metadataLen(newUserdata.sizeof()).metadata(newUserdata); + } + }); + }))) + .build() + .sizeof())); + + encoder = encodeSyncGroupRequest; + } + else + { + encoder = encodeJoinGroupRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + } + + private void onSynGroupRebalance( + long traceId, + long authorization) + { + nextResponseId++; + + nextJoinGroupRequestId++; + + encoder = encodeJoinGroupRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onSyncGroupResponse( + long traceId, + long authorization, + OctetsFW newAssignment) + { + nextResponseId++; + + if (newAssignment.sizeof() > 0) + { + Array32FW.Builder topicAssignmentBuilder = + topicPartitionsRW.wrap(extBuffer, 0, extBuffer.capacity()); + + final DirectBuffer buffer = newAssignment.value(); + final int limit = newAssignment.sizeof(); + + MutableInteger progress = new MutableInteger(); + + final ConsumerAssignmentMetadataFW assignment = assignmentMetadataRO.wrap(buffer, progress.get(), limit); + progress.set(assignment.limit()); + + for (int i = 0; i < assignment.metadataTopicCount(); i++) + { + ConsumerTopicPartitionFW topicPartition = topicPartitionRO + .wrap(buffer, progress.get(), limit); + + progress.set(topicPartition.limit()); + + topicAssignmentBuilder.item(ta -> + { + ta.topic(topicPartition.topic()); + int partitionCount = topicPartition.partitionCount(); + for (int t = 0; t < partitionCount; t++) + { + ConsumerPartitionFW partition = partitionRO.wrap(buffer, progress.get(), limit); + progress.set(partition.limit()); + + ta.partitionsItem(p -> p.partitionId(partition.partitionId())); + } + + ConsumerAssignmentUserdataFW assignmentUserdata = + assignmentUserdataRO.wrap(buffer, progress.get(), limit); + OctetsFW userdata = assignmentUserdata.userdata(); + + progress.set(assignmentUserdata.limit()); + + assignmentConsumersRO.wrap(userdata.value(), 0, userdata.sizeof()); + ta.userdata(assignmentConsumersRO); + }); + + } + + Array32FW topicAssignment = topicAssignmentBuilder.build(); + + delegate.doApplicationData(traceId, authorization, topicAssignment.buffer(), topicAssignment.offset(), + topicAssignment.sizeof()); + } + else + { + delegate.doApplicationData(traceId, authorization, EMPTY_OCTETS.buffer(), EMPTY_OCTETS.offset(), + EMPTY_OCTETS.sizeof()); + } + + if (heartbeatRequestId != NO_CANCEL_ID) + { + signaler.cancel(heartbeatRequestId); + heartbeatRequestId = NO_CANCEL_ID; + } + + encoder = encodeHeartbeatRequest; + + heartbeatRequestId = signaler.signalAt(currentTimeMillis() + delegate.timeout / 2, + originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onHeartbeatResponse( + long traceId, + long authorization) + { + nextResponseId++; + + if (heartbeatRequestId != NO_CANCEL_ID) + { + signaler.cancel(heartbeatRequestId); + heartbeatRequestId = NO_CANCEL_ID; + } + + encoder = encodeHeartbeatRequest; + heartbeatRequestId = signaler.signalAt(currentTimeMillis() + delegate.timeout / 2, + originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onLeaveGroupResponse( + long traceId, + long authorization) + { + delegate.groupMembership.memberIds.remove(delegate.groupId); + + doNetworkEnd(traceId, authorization); + doNetworkReset(traceId); + + delegate.doApplicationEnd(traceId); + delegate.doApplicationResetIfNecessary(traceId, EMPTY_OCTETS); + } + + private void onRebalanceError( + long traceId, + long authorization) + { + nextResponseId++; + + nextJoinGroupRequestId++; + + encoder = encodeJoinGroupRequest; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void cleanupNetwork( + long traceId, + long authorization) + { + doNetworkEnd(traceId, authorization); + doNetworkReset(traceId); + } + + private void onError( + long traceId) + { + doNetworkAbort(traceId); + doNetworkReset(traceId); + + delegate.cleanupApplication(traceId, EMPTY_OCTETS); + } + + private void cleanupDecodeSlotIfNecessary() + { + if (decodeSlot != NO_SLOT) + { + decodePool.release(decodeSlot); + decodeSlot = NO_SLOT; + decodeSlotOffset = 0; + decodeSlotReserved = 0; + } + } + + private void cleanupEncodeSlotIfNecessary() + { + if (encodeSlot != NO_SLOT) + { + encodePool.release(encodeSlot); + encodeSlot = NO_SLOT; + encodeSlotOffset = 0; + encodeSlotTraceId = 0; + } + } + } + + private final class GroupMembership + { + public final String instanceId; + public final Map memberIds; + + GroupMembership( + String instanceId) + { + this.instanceId = instanceId; + this.memberIds = new Object2ObjectHashMap<>(); + } + } + + private final class MemberProtocol + { + private final String memberId; + private final OctetsFW metadata; + + MemberProtocol( + String memberId, + OctetsFW metadata) + { + + this.memberId = memberId; + this.metadata = metadata; + } + } +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientMetaFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientMetaFactory.java index b572d3a30d..7e21af2c0b 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientMetaFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientMetaFactory.java @@ -31,11 +31,11 @@ import org.agrona.collections.LongLongConsumer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.String16FW; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientOffsetFetchFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientOffsetFetchFactory.java new file mode 100644 index 0000000000..b072755903 --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientOffsetFetchFactory.java @@ -0,0 +1,1644 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.engine.buffer.BufferPool.NO_SLOT; +import static java.util.Objects.requireNonNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.LongFunction; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.Int2ObjectHashMap; +import org.agrona.collections.LongLongConsumer; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; +import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.RequestHeaderFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.ResponseHeaderFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.OffsetFetchPartitionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.OffsetFetchRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.OffsetFetchResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.OffsetFetchTopicRequestFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.group.OffsetFetchTopicResponseFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.rebalance.PartitionIndexFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaDataExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaOffsetFetchBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.SignalFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; +import io.aklivity.zilla.runtime.engine.concurrent.Signaler; + + +public final class KafkaClientOffsetFetchFactory extends KafkaClientSaslHandshaker implements BindingHandler +{ + private static final int ERROR_NONE = 0; + + private static final int SIGNAL_NEXT_REQUEST = 1; + + private static final DirectBuffer EMPTY_BUFFER = new UnsafeBuffer(); + private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(EMPTY_BUFFER, 0, 0); + private static final Consumer EMPTY_EXTENSION = ex -> {}; + + private static final short OFFSET_FETCH_API_KEY = 9; + private static final short OFFSET_FETCH_API_VERSION = 0; + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final AbortFW abortRO = new AbortFW(); + private final ResetFW resetRO = new ResetFW(); + private final WindowFW windowRO = new WindowFW(); + private final SignalFW signalRO = new SignalFW(); + private final ExtensionFW extensionRO = new ExtensionFW(); + private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); + private final KafkaResetExFW.Builder kafkaResetExRW = new KafkaResetExFW.Builder(); + + private final RequestHeaderFW.Builder requestHeaderRW = new RequestHeaderFW.Builder(); + private final OffsetFetchRequestFW.Builder offsetFetchRequestRW = new OffsetFetchRequestFW.Builder(); + private final OffsetFetchTopicRequestFW.Builder offsetFetchTopicRequestRW = new OffsetFetchTopicRequestFW.Builder(); + private final PartitionIndexFW.Builder partitionIndexRW = new PartitionIndexFW.Builder(); + + private final ResponseHeaderFW responseHeaderRO = new ResponseHeaderFW(); + private final OffsetFetchResponseFW offsetFetchResponseRO = new OffsetFetchResponseFW(); + private final OffsetFetchTopicResponseFW offsetFetchTopicResponseRO = new OffsetFetchTopicResponseFW(); + private final OffsetFetchPartitionFW offsetFetchPartitionRO = new OffsetFetchPartitionFW(); + + private final KafkaOffsetFetchClientDecoder decodeSaslHandshakeResponse = this::decodeSaslHandshakeResponse; + private final KafkaOffsetFetchClientDecoder decodeSaslHandshake = this::decodeSaslHandshake; + private final KafkaOffsetFetchClientDecoder decodeSaslHandshakeMechanisms = this::decodeSaslHandshakeMechanisms; + private final KafkaOffsetFetchClientDecoder decodeSaslHandshakeMechanism = this::decodeSaslHandshakeMechanism; + private final KafkaOffsetFetchClientDecoder decodeSaslAuthenticateResponse = this::decodeSaslAuthenticateResponse; + private final KafkaOffsetFetchClientDecoder decodeSaslAuthenticate = this::decodeSaslAuthenticate; + private final KafkaOffsetFetchClientDecoder decodeOffsetFetchResponse = this::decodeOffsetFetchResponse; + private final KafkaOffsetFetchClientDecoder decodeOffsetFetchTopics = this::decodeOffsetFetchTopics; + private final KafkaOffsetFetchClientDecoder decodeOffsetFetchTopic = this::decodeOffsetFetchTopic; + private final KafkaOffsetFetchClientDecoder decodeOffsetFetchPartitions = this::decodeOffsetFetchPartitions; + private final KafkaOffsetFetchClientDecoder decodeOffsetFetchPartition = this::decodeOffsetFetchPartition; + + private final KafkaOffsetFetchClientDecoder decodeIgnoreAll = this::decodeIgnoreAll; + private final KafkaOffsetFetchClientDecoder decodeReject = this::decodeReject; + + private final int kafkaTypeId; + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final BufferPool decodePool; + private final BufferPool encodePool; + private final Signaler signaler; + private final BindingHandler streamFactory; + private final LongFunction supplyBinding; + private final LongFunction supplyClientRoute; + + public KafkaClientOffsetFetchFactory( + KafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding, + LongFunction supplyClientRoute) + { + super(config, context); + this.kafkaTypeId = context.supplyTypeId(KafkaBinding.NAME); + this.signaler = context.signaler(); + this.streamFactory = context.streamFactory(); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.decodePool = context.bufferPool(); + this.encodePool = context.bufferPool(); + this.supplyBinding = supplyBinding; + this.supplyClientRoute = supplyClientRoute; + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer application) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long affinity = begin.affinity(); + final long authorization = begin.authorization(); + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extensionRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()); + final KafkaBeginExFW kafkaBeginEx = beginEx != null && beginEx.typeId() == kafkaTypeId ? + kafkaBeginExRO.tryWrap(extension.buffer(), extension.offset(), extension.limit()) : null; + + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_OFFSET_FETCH; + final KafkaOffsetFetchBeginExFW kafkaOffsetFetchBeginEx = kafkaBeginEx.offsetFetch(); + final String groupId = kafkaOffsetFetchBeginEx.groupId().asString(); + List topics = new ArrayList<>(); + kafkaOffsetFetchBeginEx.topics().forEach(t -> + { + List partitions = new ArrayList<>(); + t.partitions().forEach(p -> partitions.add(p.partitionId())); + topics.add(new KafkaOffsetFetchTopic(t.topic().asString(), partitions)); + }); + + + MessageConsumer newStream = null; + + final KafkaBindingConfig binding = supplyBinding.apply(routedId); + final KafkaRouteConfig resolved = binding != null ? + binding.resolve(authorization, null, groupId) : null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + final KafkaSaslConfig sasl = binding.sasl(); + + newStream = new KafkaOffsetFetchStream( + application, + originId, + routedId, + initialId, + affinity, + resolvedId, + groupId, + topics, + sasl)::onApplication; + } + + return newStream; + } + + private MessageConsumer newStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + final MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Consumer extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer payload, + int offset, + int length, + Consumer extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload, offset, length) + .extension(extension) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doDataNull( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Consumer extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Flyweight extension) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + @FunctionalInterface + private interface KafkaOffsetFetchClientDecoder + { + int decode( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int progress, + int limit); + } + + private int decodeOffsetFetchResponse( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final ResponseHeaderFW responseHeader = responseHeaderRO.tryWrap(buffer, progress, limit); + if (responseHeader == null) + { + break decode; + } + + progress = responseHeader.limit(); + + client.decodeableResponseBytes = responseHeader.length(); + + final OffsetFetchResponseFW offsetFetchResponse = offsetFetchResponseRO.tryWrap(buffer, progress, limit); + if (offsetFetchResponse == null) + { + break decode; + } + + progress = offsetFetchResponse.limit(); + + client.decodeableResponseBytes -= offsetFetchResponse.sizeof(); + assert client.decodeableResponseBytes >= 0; + + client.decodeableTopics = offsetFetchResponse.topicCount(); + client.decoder = decodeOffsetFetchTopics; + } + + return progress; + } + + private int decodeOffsetFetchTopics( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + if (client.decodeableTopics == 0) + { + assert client.decodeableResponseBytes == 0; + + client.decoder = decodeOffsetFetchResponse; + } + else + { + client.decoder = decodeOffsetFetchTopic; + } + + return progress; + } + + private int decodeOffsetFetchTopic( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final OffsetFetchTopicResponseFW topicOffsetFetch = offsetFetchTopicResponseRO.tryWrap(buffer, progress, limit); + if (topicOffsetFetch == null) + { + break decode; + } + + final String topic = topicOffsetFetch.name().asString(); + + client.onDecodeTopic(traceId, authorization, topic); + + progress = topicOffsetFetch.limit(); + + client.decodeableResponseBytes -= topicOffsetFetch.sizeof(); + assert client.decodeableResponseBytes >= 0; + + client.decodeablePartitions = topicOffsetFetch.partitionCount(); + client.decoder = decodeOffsetFetchPartitions; + } + + return progress; + } + + private int decodeOffsetFetchPartitions( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + if (client.decodeablePartitions == 0) + { + client.decodeableTopics--; + assert client.decodeableTopics >= 0; + + client.decoder = decodeOffsetFetchTopics; + client.onDecodeOffsetFetchResponse(traceId); + } + else + { + client.decoder = decodeOffsetFetchPartition; + } + + return progress; + } + + private int decodeOffsetFetchPartition( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + final int length = limit - progress; + + decode: + if (length != 0) + { + final OffsetFetchPartitionFW partition = offsetFetchPartitionRO.tryWrap(buffer, progress, limit); + if (partition == null) + { + break decode; + } + + final int partitionError = partition.errorCode(); + final int partitionId = partition.partitionIndex(); + final long offsetCommitted = partition.committedOffset(); + + client.onDecodePartition(traceId, partitionId, offsetCommitted, partitionError); + + progress = partition.limit(); + + client.decodeableResponseBytes -= partition.sizeof(); + assert client.decodeableResponseBytes >= 0; + + client.decodeablePartitions--; + assert client.decodeablePartitions >= 0; + + client.decoder = decodeOffsetFetchPartitions; + } + + return progress; + } + + private int decodeReject( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + client.doNetworkResetIfNecessary(traceId); + client.decoder = decodeIgnoreAll; + return limit; + } + + private int decodeIgnoreAll( + KafkaOffsetFetchStream.KafkaOffsetFetchClient client, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int progress, + int limit) + { + return limit; + } + + private final class KafkaOffsetFetchStream + { + private final MessageConsumer application; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final long affinity; + private final KafkaOffsetFetchClient client; + private final KafkaClientRoute clientRoute; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private long replyBudgetId; + + KafkaOffsetFetchStream( + MessageConsumer application, + long originId, + long routedId, + long initialId, + long affinity, + long resolvedId, + String groupId, + List topics, + KafkaSaslConfig sasl) + { + this.application = application; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.affinity = affinity; + this.clientRoute = supplyClientRoute.apply(resolvedId); + this.client = new KafkaOffsetFetchClient(routedId, resolvedId, groupId, topics, sasl); + } + + private void onApplication( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onApplicationBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onApplicationData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onApplicationEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onApplicationAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onApplicationWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onApplicationReset(reset); + break; + default: + break; + } + } + + private void onApplicationBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + + state = KafkaState.openingInitial(state); + + client.doNetworkBegin(traceId, authorization, affinity); + } + + private void onApplicationData( + DataFW data) + { + final long traceId = data.traceId(); + + client.cleanupNetwork(traceId); + } + + private void onApplicationEnd( + EndFW end) + { + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + state = KafkaState.closedInitial(state); + + client.doNetworkEnd(traceId, authorization); + } + + private void onApplicationAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedInitial(state); + + client.doNetworkAbortIfNecessary(traceId); + } + + private void onApplicationWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + this.replyAck = acknowledge; + this.replyMax = maximum; + this.replyPad = padding; + this.replyBudgetId = budgetId; + + assert replyAck <= replySeq; + } + + private void onApplicationReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + client.doNetworkResetIfNecessary(traceId); + } + + private boolean isApplicationReplyOpen() + { + return KafkaState.replyOpening(state); + } + + private void doApplicationBeginIfNecessary( + long traceId, + long authorization) + { + if (!KafkaState.replyOpening(state)) + { + doApplicationBegin(traceId, authorization); + } + } + + private void doApplicationBegin( + long traceId, + long authorization) + { + state = KafkaState.openingReply(state); + + doBegin(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, EMPTY_EXTENSION); + } + + private void doApplicationData( + long traceId, + long authorization, + KafkaDataExFW extension) + { + final int reserved = replyPad; + + doDataNull(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, replyBudgetId, reserved, extension); + + replySeq += reserved; + + assert replyAck <= replySeq; + } + + private void doApplicationEnd( + long traceId) + { + state = KafkaState.closedReply(state); + //client.stream = nullIfClosed(state, client.stream); + doEnd(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, client.authorization, EMPTY_EXTENSION); + } + + private void doApplicationAbort( + long traceId) + { + state = KafkaState.closedReply(state); + //client.stream = nullIfClosed(state, client.stream); + doAbort(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, client.authorization, EMPTY_EXTENSION); + } + + private void doApplicationWindow( + long traceId, + long budgetId, + int minInitialNoAck, + int minInitialPad, + int minInitialMax) + { + final long newInitialAck = Math.max(initialSeq - minInitialNoAck, initialAck); + + if (newInitialAck > initialAck || minInitialMax > initialMax || !KafkaState.initialOpened(state)) + { + initialAck = newInitialAck; + assert initialAck <= initialSeq; + + initialMax = minInitialMax; + + state = KafkaState.openedInitial(state); + + doWindow(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, client.authorization, budgetId, minInitialPad); + } + } + + private void doApplicationReset( + long traceId, + Flyweight extension) + { + state = KafkaState.closedInitial(state); + //client.stream = nullIfClosed(state, client.stream); + + doReset(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, client.authorization, extension); + } + + private void doApplicationAbortIfNecessary( + long traceId) + { + if (KafkaState.replyOpening(state) && !KafkaState.replyClosed(state)) + { + doApplicationAbort(traceId); + } + } + + private void doApplicationResetIfNecessary( + long traceId, + Flyweight extension) + { + if (KafkaState.initialOpening(state) && !KafkaState.initialClosed(state)) + { + doApplicationReset(traceId, extension); + } + } + + private void cleanupApplication( + long traceId, + int error) + { + final KafkaResetExFW kafkaResetEx = kafkaResetExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .error(error) + .build(); + + cleanupApplication(traceId, kafkaResetEx); + } + + private void cleanupApplication( + long traceId, + Flyweight extension) + { + doApplicationResetIfNecessary(traceId, extension); + doApplicationAbortIfNecessary(traceId); + } + + private final class KafkaOffsetFetchClient extends KafkaSaslClient + { + private final LongLongConsumer encodeSaslHandshakeRequest = this::doEncodeSaslHandshakeRequest; + private final LongLongConsumer encodeSaslAuthenticateRequest = this::doEncodeSaslAuthenticateRequest; + private final LongLongConsumer encodeOffsetFetchRequest = this::doEncodeOffsetFetchRequest; + + private final String groupId; + private final List topics; + private final Int2ObjectHashMap topicPartitions; + private String newTopic; + + private MessageConsumer network; + private int state; + private int decodeableResponseBytes; + private int decodeableTopics; + private int decodeablePartitions; + private long authorization; + + private long initialSeq; + private long initialAck; + private int initialMax; + private int initialPad; + private long initialBudgetId; + + private long replySeq; + private long replyAck; + private int replyMax; + + private int encodeSlot = NO_SLOT; + private int encodeSlotOffset; + private long encodeSlotTraceId; + + private int decodeSlot = NO_SLOT; + private int decodeSlotOffset; + private int decodeSlotReserved; + + private int nextResponseId; + + private KafkaOffsetFetchClientDecoder decoder; + private LongLongConsumer encoder; + + KafkaOffsetFetchClient( + long originId, + long routedId, + String groupId, + List topics, + KafkaSaslConfig sasl) + { + super(sasl, originId, routedId); + this.groupId = requireNonNull(groupId); + this.topics = topics; + this.topicPartitions = new Int2ObjectHashMap<>(); + + this.encoder = sasl != null ? encodeSaslHandshakeRequest : encodeOffsetFetchRequest; + this.decoder = decodeReject; + } + + private void onNetwork( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onNetworkBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onNetworkData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onNetworkEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onNetworkAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onNetworkReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onNetworkWindow(window); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onNetworkSignal(signal); + break; + default: + break; + } + } + + private void onNetworkBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + authorization = begin.authorization(); + state = KafkaState.openingReply(state); + + doNetworkWindow(traceId, 0L, 0, 0, decodePool.slotCapacity()); + } + + private void onNetworkData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long budgetId = data.budgetId(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + data.reserved(); + authorization = data.authorization(); + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + cleanupNetwork(traceId); + } + else + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + cleanupNetwork(traceId); + } + else + { + final OctetsFW payload = data.payload(); + int reserved = data.reserved(); + int offset = payload.offset(); + int limit = payload.limit(); + + final MutableDirectBuffer buffer = decodePool.buffer(decodeSlot); + buffer.putBytes(decodeSlotOffset, payload.buffer(), offset, limit - offset); + decodeSlotOffset += limit - offset; + decodeSlotReserved += reserved; + + offset = 0; + limit = decodeSlotOffset; + reserved = decodeSlotReserved; + + decodeNetwork(traceId, authorization, budgetId, reserved, buffer, offset, limit); + } + } + } + + private void onNetworkEnd( + EndFW end) + { + final long traceId = end.traceId(); + + state = KafkaState.closedReply(state); + + cleanupDecodeSlotIfNecessary(); + + if (!isApplicationReplyOpen()) + { + cleanupNetwork(traceId); + } + else if (decodeSlot == NO_SLOT) + { + doApplicationEnd(traceId); + } + } + + private void onNetworkAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedReply(state); + + cleanupNetwork(traceId); + } + + private void onNetworkReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + cleanupNetwork(traceId); + } + + private void onNetworkWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= initialSeq; + assert acknowledge >= initialAck; + assert maximum + acknowledge >= initialMax + initialAck; + + this.initialAck = acknowledge; + this.initialMax = maximum; + this.initialPad = padding; + this.initialBudgetId = budgetId; + + assert initialAck <= initialSeq; + + this.authorization = window.authorization(); + + state = KafkaState.openedInitial(state); + + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer buffer = encodePool.buffer(encodeSlot); + final int limit = encodeSlotOffset; + + encodeNetwork(encodeSlotTraceId, authorization, budgetId, buffer, 0, limit); + } + + doEncodeRequestIfNecessary(traceId, budgetId); + } + + private void onNetworkSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final int signalId = signal.signalId(); + + if (signalId == SIGNAL_NEXT_REQUEST) + { + doEncodeRequestIfNecessary(traceId, initialBudgetId); + } + } + + private void doNetworkBegin( + long traceId, + long authorization, + long affinity) + { + state = KafkaState.openingInitial(state); + + network = newStream(this::onNetwork, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, EMPTY_EXTENSION); + } + + @Override + protected void doNetworkData( + long traceId, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(encodeSlotOffset, buffer, offset, limit - offset); + encodeSlotOffset += limit - offset; + encodeSlotTraceId = traceId; + + buffer = encodeBuffer; + offset = 0; + limit = encodeSlotOffset; + } + + encodeNetwork(traceId, authorization, budgetId, buffer, offset, limit); + } + + private void doNetworkEnd( + long traceId, + long authorization) + { + state = KafkaState.closedInitial(state); + + cleanupEncodeSlotIfNecessary(); + + doEnd(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + } + + private void doNetworkAbortIfNecessary( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doAbort(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_EXTENSION); + state = KafkaState.closedInitial(state); + } + + cleanupEncodeSlotIfNecessary(); + } + + private void doNetworkResetIfNecessary( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doReset(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + state = KafkaState.closedReply(state); + } + + cleanupDecodeSlotIfNecessary(); + } + + private void doNetworkWindow( + long traceId, + long budgetId, + int minReplyNoAck, + int minReplyPad, + int minReplyMax) + { + final long newReplyAck = Math.max(replySeq - minReplyNoAck, replyAck); + + if (newReplyAck > replyAck || minReplyMax > replyMax || !KafkaState.replyOpened(state)) + { + replyAck = newReplyAck; + assert replyAck <= replySeq; + + replyMax = minReplyMax; + + state = KafkaState.openedReply(state); + + doWindow(network, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, minReplyPad); + } + } + + private void doEncodeRequestIfNecessary( + long traceId, + long budgetId) + { + if (nextRequestId == nextResponseId) + { + encoder.accept(traceId, budgetId); + } + } + + private void doEncodeOffsetFetchRequest( + long traceId, + long budgetId) + { + if (KafkaConfiguration.DEBUG) + { + System.out.format("[client] %s OFFSET FETCH\n", groupId); + } + + final MutableDirectBuffer encodeBuffer = writeBuffer; + final int encodeOffset = DataFW.FIELD_OFFSET_PAYLOAD; + final int encodeLimit = encodeBuffer.capacity(); + + int encodeProgress = encodeOffset; + + final RequestHeaderFW requestHeader = requestHeaderRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .length(0) + .apiKey(OFFSET_FETCH_API_KEY) + .apiVersion(OFFSET_FETCH_API_VERSION) + .correlationId(0) + .clientId((String) null) + .build(); + + encodeProgress = requestHeader.limit(); + + final OffsetFetchRequestFW offsetFetchRequest = + offsetFetchRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .groupId(groupId) + .topicCount(topics.size()) + .build(); + + encodeProgress = offsetFetchRequest.limit(); + + for (KafkaOffsetFetchTopic topic: topics) + { + final OffsetFetchTopicRequestFW offsetFetchTopicRequest = + offsetFetchTopicRequestRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .topic(topic.topic) + .partitionsCount(topic.partitions.size()) + .build(); + encodeProgress = offsetFetchTopicRequest.limit(); + + for (Integer partition : topic.partitions) + { + final PartitionIndexFW partitionIndex = + partitionIndexRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .index(partition) + .build(); + encodeProgress = partitionIndex.limit(); + } + + } + + final int requestId = nextRequestId++; + final int requestSize = encodeProgress - encodeOffset - RequestHeaderFW.FIELD_OFFSET_API_KEY; + + requestHeaderRW.wrap(encodeBuffer, requestHeader.offset(), requestHeader.limit()) + .length(requestSize) + .apiKey(requestHeader.apiKey()) + .apiVersion(requestHeader.apiVersion()) + .correlationId(requestId) + .clientId(requestHeader.clientId().asString()) + .build(); + + doNetworkData(traceId, budgetId, encodeBuffer, encodeOffset, encodeProgress); + + decoder = decodeOffsetFetchResponse; + } + + private void encodeNetwork( + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + final int maxLength = limit - offset; + final int initialWin = initialMax - (int)(initialSeq - initialAck); + final int length = Math.max(Math.min(initialWin - initialPad, maxLength), 0); + + if (length > 0) + { + final int reserved = length + initialPad; + + doData(network, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, buffer, offset, length, EMPTY_EXTENSION); + + initialSeq += reserved; + + assert initialAck <= initialSeq; + } + + final int remaining = maxLength - length; + if (remaining > 0) + { + if (encodeSlot == NO_SLOT) + { + encodeSlot = encodePool.acquire(initialId); + } + + if (encodeSlot == NO_SLOT) + { + cleanupNetwork(traceId); + } + else + { + final MutableDirectBuffer encodeBuffer = encodePool.buffer(encodeSlot); + encodeBuffer.putBytes(0, buffer, offset + length, remaining); + encodeSlotOffset = remaining; + } + } + else + { + cleanupEncodeSlotIfNecessary(); + } + } + + private void decodeNetwork( + long traceId, + long authorization, + long budgetId, + int reserved, + MutableDirectBuffer buffer, + int offset, + int limit) + { + KafkaOffsetFetchClientDecoder previous = null; + int progress = offset; + while (progress <= limit && previous != decoder) + { + previous = decoder; + progress = decoder.decode(this, traceId, authorization, budgetId, reserved, buffer, offset, progress, limit); + } + + if (progress < limit) + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = decodePool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + cleanupNetwork(traceId); + } + else + { + final MutableDirectBuffer decodeBuffer = decodePool.buffer(decodeSlot); + decodeBuffer.putBytes(0, buffer, progress, limit - progress); + decodeSlotOffset = limit - progress; + decodeSlotReserved = (limit - progress) * reserved / (limit - offset); + } + + doNetworkWindow(traceId, budgetId, decodeSlotOffset, 0, replyMax); + } + else + { + cleanupDecodeSlotIfNecessary(); + + if (KafkaState.replyClosing(state)) + { + doApplicationEnd(traceId); + } + else if (reserved > 0) + { + doNetworkWindow(traceId, budgetId, 0, 0, replyMax); + } + } + } + + @Override + protected void doDecodeSaslHandshakeResponse( + long traceId) + { + decoder = decodeSaslHandshakeResponse; + } + + @Override + protected void doDecodeSaslHandshake( + long traceId) + { + decoder = decodeSaslHandshake; + } + + @Override + protected void doDecodeSaslHandshakeMechanisms( + long traceId) + { + decoder = decodeSaslHandshakeMechanisms; + } + + @Override + protected void doDecodeSaslHandshakeMechansim( + long traceId) + { + decoder = decodeSaslHandshakeMechanism; + } + + @Override + protected void doDecodeSaslAuthenticateResponse( + long traceId) + { + decoder = decodeSaslAuthenticateResponse; + } + + @Override + protected void doDecodeSaslAuthenticate( + long traceId) + { + decoder = decodeSaslAuthenticate; + } + + @Override + protected void onDecodeSaslHandshakeResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + client.encoder = client.encodeSaslAuthenticateRequest; + client.decoder = decodeSaslAuthenticateResponse; + break; + default: + cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslAuthenticateResponse( + long traceId, + long authorization, + int errorCode) + { + switch (errorCode) + { + case ERROR_NONE: + client.encoder = client.encodeOffsetFetchRequest; + client.decoder = decodeOffsetFetchResponse; + break; + default: + cleanupApplication(traceId, errorCode); + doNetworkEnd(traceId, authorization); + break; + } + } + + @Override + protected void onDecodeSaslResponse( + long traceId) + { + nextResponseId++; + signaler.signalNow(originId, routedId, initialId, SIGNAL_NEXT_REQUEST, 0); + } + + private void onDecodeOffsetFetchResponse( + long traceId) + { + doApplicationBeginIfNecessary(traceId, authorization); + doApplicationWindow(traceId, 0L, 0, 0, 0); + + final KafkaDataExFW kafkaDataEx = kafkaDataExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .offsetFetch(m -> + m.topic(t -> + t.topic(newTopic) + .offsets(o -> topicPartitions.forEach((k, v) -> + o.item(to -> to + .partitionId(k) + .partitionOffset(v) + ))))) + .build(); + + doApplicationData(traceId, authorization, kafkaDataEx); + + nextResponseId++; + } + + public void onDecodeTopic( + long traceId, + long authorization, + String topic) + { + newTopic = topic; + } + + public void onDecodePartition( + long traceId, + int partitionId, + long offsetCommitted, + int partitionError) + { + if (partitionError == ERROR_NONE) + { + topicPartitions.put(partitionId, (Long) offsetCommitted); + } + } + + private void cleanupNetwork( + long traceId) + { + doNetworkResetIfNecessary(traceId); + doNetworkAbortIfNecessary(traceId); + + cleanupApplication(traceId, EMPTY_OCTETS); + } + + private void cleanupDecodeSlotIfNecessary() + { + if (decodeSlot != NO_SLOT) + { + decodePool.release(decodeSlot); + decodeSlot = NO_SLOT; + decodeSlotOffset = 0; + decodeSlotReserved = 0; + } + } + + private void cleanupEncodeSlotIfNecessary() + { + if (encodeSlot != NO_SLOT) + { + encodePool.release(encodeSlot); + encodeSlot = NO_SLOT; + encodeSlotOffset = 0; + encodeSlotTraceId = 0; + } + } + } + } + + +} diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java index d312acf267..c4782b128e 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java @@ -38,11 +38,11 @@ import org.agrona.collections.LongLongConsumer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaBindingConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaRouteConfig; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.kafka.internal.types.KafkaAckMode; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientSaslHandshaker.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientSaslHandshaker.java index 00ed048dbe..54de465f9f 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientSaslHandshaker.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientSaslHandshaker.java @@ -33,9 +33,9 @@ import org.agrona.collections.LongLongConsumer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaSaslConfig; -import io.aklivity.zilla.runtime.binding.kafka.internal.config.ScramMechanism; +import io.aklivity.zilla.runtime.binding.kafka.internal.config.KafkaScramMechanism; import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.RequestHeaderFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.ResponseHeaderFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.codec.sasl.SaslAuthenticateRequestFW; @@ -90,7 +90,7 @@ public abstract class KafkaClientSaslHandshaker private MessageDigest messageDigest; private Mac mac; private Supplier nonceSupplier; - private ScramMechanism mechanism; + private KafkaScramMechanism mechanism; private Matcher serverResponseMatcher; private byte[] result, ui, prev; @@ -113,8 +113,8 @@ public abstract class KafkaSaslClient protected final KafkaSaslConfig sasl; protected final long originId; protected final long routedId; - protected final long initialId; - protected final long replyId; + protected long initialId; + protected long replyId; protected int nextRequestId; @@ -321,7 +321,7 @@ private void doEncodeSaslScramFinalAuthenticateRequest( long traceId, long budgetId) { - mechanism = ScramMechanism.forMechanismName(sasl.mechanism.toUpperCase()); + mechanism = KafkaScramMechanism.forMechanismName(sasl.mechanism.toUpperCase()); try { messageDigest = MessageDigest.getInstance(mechanism.hashAlgorithm()); diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaMergedFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaMergedFactory.java index ef921f56df..5a0a38f09c 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaMergedFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaMergedFactory.java @@ -34,8 +34,10 @@ import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.collections.Int2IntHashMap; +import org.agrona.collections.Int2ObjectHashMap; import org.agrona.collections.Long2LongHashMap; import org.agrona.collections.MutableInteger; +import org.agrona.collections.MutableReference; import org.agrona.concurrent.UnsafeBuffer; import io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBinding; @@ -71,6 +73,8 @@ import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ExtensionFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.FlushFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaConsumerAssignmentFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaConsumerDataExFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaDataExFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaDescribeDataExFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaFetchDataExFW; @@ -81,6 +85,7 @@ import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaMergedFlushExFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaMetaDataExFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.KafkaTopicPartitionFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.ResetFW; import io.aklivity.zilla.runtime.binding.kafka.internal.types.stream.WindowFW; import io.aklivity.zilla.runtime.engine.EngineContext; @@ -142,6 +147,7 @@ public final class KafkaMergedFactory implements BindingHandler private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); + private final KafkaResetExFW.Builder kafkaResetExRW = new KafkaResetExFW.Builder(); private final MutableInteger partitionCount = new MutableInteger(); private final MutableInteger initialNoAckRW = new MutableInteger(); @@ -958,7 +964,8 @@ private void doReset( long acknowledge, int maximum, long traceId, - long authorization) + long authorization, + Consumer extension) { final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) .originId(originId) @@ -969,6 +976,7 @@ private void doReset( .maximum(maximum) .traceId(traceId) .authorization(authorization) + .extension(extension) .build(); sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); @@ -1001,6 +1009,8 @@ private final class KafkaMergedStream private final KafkaUnmergedMetaStream metaStream; private final List fetchStreams; private final List produceStreams; + private final Int2ObjectHashMap consumers; + private final Int2IntHashMap leadersByAssignedId; private final Int2IntHashMap leadersByPartitionId; private final Long2LongHashMap latestOffsetByPartitionId; private final Long2LongHashMap stableOffsetByPartitionId; @@ -1035,7 +1045,11 @@ private final class KafkaMergedStream private int fetchStreamIndex; private long mergedReplyBudgetId = NO_CREDITOR_INDEX; + private KafkaUnmergedConsumerStream consumerStream; private KafkaUnmergedProduceStream producer; + private String groupId; + private String consumerId; + private int timeout; KafkaMergedStream( MessageConsumer sender, @@ -1067,7 +1081,9 @@ private final class KafkaMergedStream this.metaStream = new KafkaUnmergedMetaStream(this); this.fetchStreams = new ArrayList<>(); this.produceStreams = new ArrayList<>(); + this.consumers = new Int2ObjectHashMap<>(); this.leadersByPartitionId = new Int2IntHashMap(-1); + this.leadersByAssignedId = new Int2IntHashMap(-1); this.latestOffsetByPartitionId = new Long2LongHashMap(-3); this.stableOffsetByPartitionId = new Long2LongHashMap(-3); this.nextOffsetsById = initialOffsetsById; @@ -1148,6 +1164,14 @@ private void onMergedInitialBegin( this.maximumOffset = asMaximumOffset(mergedBeginEx.partitions()); this.filters = asMergedFilters(filters); this.evaluation = mergedBeginEx.evaluation(); + this.groupId = mergedBeginEx.groupId().asString(); + this.consumerId = mergedBeginEx.consumerId().asString(); + this.timeout = mergedBeginEx.timeout(); + + if (groupId != null && !groupId.isEmpty()) + { + this.consumerStream = new KafkaUnmergedConsumerStream(this); + } describeStream.doDescribeInitialBegin(traceId); } @@ -1179,6 +1203,7 @@ private void onMergedInitialData( final int flags = data.flags(); final OctetsFW payload = data.payload(); final OctetsFW extension = data.extension(); + MutableReference consumerId = new MutableReference<>(); if (producer == null) { @@ -1192,22 +1217,37 @@ private void onMergedInitialData( assert kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED; final KafkaMergedDataExFW kafkaMergedDataEx = kafkaDataEx.merged(); final KafkaKeyFW key = kafkaMergedDataEx.key(); + final KafkaKeyFW hashKey = kafkaMergedDataEx.hashKey(); final KafkaOffsetFW partition = kafkaMergedDataEx.partition(); final int partitionId = partition.partitionId(); - final int nextPartitionId = partitionId == DYNAMIC_PARTITION ? nextPartitionData(key) : partitionId; + final int nextPartitionId = partitionId == DYNAMIC_PARTITION ? nextPartitionData(hashKey, key) : partitionId; final KafkaUnmergedProduceStream newProducer = findProducePartitionLeader(nextPartitionId); - assert newProducer != null; // TODO this.producer = newProducer; - } - assert producer != null; + if (this.producer == null) + { + consumerId.set(consumers.get(nextPartitionId)); + } + } - producer.doProduceInitialData(traceId, reserved, flags, budgetId, payload, extension); + if (this.producer != null) + { + producer.doProduceInitialData(traceId, reserved, flags, budgetId, payload, extension); - if ((flags & FLAGS_FIN) != FLAGS_NONE) + if ((flags & FLAGS_FIN) != FLAGS_NONE) + { + this.producer = null; + } + } + else { - this.producer = null; + doMergedInitialReset(traceId, ex -> ex.set((b, o, l) -> kafkaResetExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .error(0) + .consumerId(consumerId.get()) + .build() + .sizeof())); } } } @@ -1220,10 +1260,13 @@ private KafkaOffsetType asMaximumOffset( } private int nextPartitionData( + KafkaKeyFW hashKey, KafkaKeyFW key) { final int partitionCount = leadersByPartitionId.size(); - final int keyHash = key.length() != -1 ? defaultKeyHash(key) : nextNullKeyHashData++; + final int keyHash = hashKey.length() != -1 ? defaultKeyHash(hashKey) : + key.length() != -1 ? defaultKeyHash(key) : + nextNullKeyHashData++; final int partitionId = partitionCount > 0 ? (0x7fff_ffff & keyHash) % partitionCount : 0; return partitionId; @@ -1291,18 +1334,18 @@ private void onMergedInitialFlush( assert kafkaFlushEx != null; assert kafkaFlushEx.kind() == KafkaFlushExFW.KIND_MERGED; final KafkaMergedFlushExFW kafkaMergedFlushEx = kafkaFlushEx.merged(); - final KafkaCapabilities newCapabilities = kafkaMergedFlushEx.capabilities().get(); - final Array32FW filters = kafkaMergedFlushEx.filters(); + final KafkaCapabilities newCapabilities = kafkaMergedFlushEx.fetch().capabilities().get(); + final Array32FW filters = kafkaMergedFlushEx.fetch().filters(); final List newFilters = asMergedFilters(filters); if (capabilities != newCapabilities) { - this.maximumOffset = asMaximumOffset(kafkaMergedFlushEx.progress()); + this.maximumOffset = asMaximumOffset(kafkaMergedFlushEx.fetch().progress()); if (hasFetchCapability(newCapabilities) && !hasFetchCapability(capabilities)) { final Long2LongHashMap initialOffsetsById = new Long2LongHashMap(-3L); - kafkaMergedFlushEx.progress().forEach(p -> + kafkaMergedFlushEx.fetch().progress().forEach(p -> { final long partitionId = p.partitionId(); if (partitionId >= 0L) @@ -1326,8 +1369,8 @@ private void onMergedInitialFlush( { if (hasProduceCapability(capabilities)) { - final KafkaOffsetFW partition = kafkaMergedFlushEx.partition(); - final KafkaKeyFW key = kafkaMergedFlushEx.key(); + final KafkaOffsetFW partition = kafkaMergedFlushEx.fetch().partition(); + final KafkaKeyFW key = kafkaMergedFlushEx.fetch().key(); if (partition != null) { final int partitionId = partition.partitionId(); @@ -1343,7 +1386,7 @@ private void onMergedInitialFlush( if (hasFetchCapability(capabilities) && !newFilters.equals(this.filters)) { this.filters = newFilters; - final int partitionCount = leadersByPartitionId.size(); + final int partitionCount = leadersByAssignedId.size(); for (int partitionId = 0; partitionId < partitionCount; partitionId++) { doFetchInitialFlush(traceId, partitionId); @@ -1620,13 +1663,14 @@ private void doMergedInitialWindow( } private void doMergedInitialReset( - long traceId) + long traceId, + Consumer extension) { assert !KafkaState.initialClosed(state); state = KafkaState.closedInitial(state); doReset(sender, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization); + traceId, authorization, extension); } private void doMergedReplyEndIfNecessary( @@ -1671,12 +1715,12 @@ private void doMergedReplyFlush( { final KafkaFlushExFW kafkaFlushExFW = kafkaFlushExRW.wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) - .merged(f -> f - .progress(ps -> nextOffsetsById.longForEach((p, o) -> - ps.item(i -> i.partitionId((int) p) - .partitionOffset(o) - .stableOffset(initialStableOffsetsById.get(p)) - .latestOffset(initialLatestOffsetsById.get(p)))))) + .merged(ff -> ff + .fetch(f -> f.progress(ps -> nextOffsetsById.longForEach((p, o) -> + ps.item(i -> i.partitionId((int) p) + .partitionOffset(o) + .stableOffset(initialStableOffsetsById.get(p)) + .latestOffset(initialLatestOffsetsById.get(p))))))) .build(); doFlush(sender, originId, routedId, replyId, replySeq, replyAck, replyMax, @@ -1725,7 +1769,7 @@ private void doMergedInitialResetIfNecessary( cleanupBudgetCreditorIfNecessary(); if (fetchStreams.isEmpty()) { - doMergedInitialReset(traceId); + doMergedInitialReset(traceId, EMPTY_EXTENSION); } } } @@ -1761,7 +1805,44 @@ private void onTopicMetaDataChanged( partitions.forEach(p -> leadersByPartitionId.put(p.partitionId(), p.leaderId())); partitionCount.value = 0; partitions.forEach(partition -> partitionCount.value++); - assert leadersByPartitionId.size() == partitionCount.value; + + if (this.consumerStream != null) + { + this.consumerStream.doConsumerInitialBeginIfNecessary(traceId); + } + else + { + leadersByAssignedId.clear(); + partitions.forEach(p -> leadersByAssignedId.put(p.partitionId(), p.leaderId())); + assert leadersByAssignedId.size() == partitionCount.value; + + doFetchPartitionsIfNecessary(traceId); + doProducePartitionsIfNecessary(traceId); + } + } + + private void onTopicConsumerDataChanged( + long traceId, + Array32FW partitions, + Array32FW newAssignments) + { + leadersByAssignedId.clear(); + partitions.forEach(p -> + { + int partitionId = p.partitionId(); + int leaderId = leadersByPartitionId.get(partitionId); + leadersByAssignedId.put(partitionId, leaderId); + }); + + consumers.clear(); + newAssignments.forEach(a -> + { + a.partitions().forEach(p -> + { + final String consumerId = a.consumerId().asString(); + consumers.put(p.partitionId(), consumerId); + }); + }); doFetchPartitionsIfNecessary(traceId); doProducePartitionsIfNecessary(traceId); @@ -1772,19 +1853,14 @@ private void doFetchPartitionsIfNecessary( { if (hasFetchCapability(capabilities)) { - final int partitionCount = leadersByPartitionId.size(); - for (int partitionId = 0; partitionId < partitionCount; partitionId++) - { - doFetchPartitionIfNecessary(traceId, partitionId); - } - assert fetchStreams.size() >= leadersByPartitionId.size(); + leadersByAssignedId.forEach((k, v) -> doFetchPartitionIfNecessary(traceId, k)); + assert fetchStreams.size() >= leadersByAssignedId.size(); - int offsetCount = nextOffsetsById.size(); - for (int partitionId = partitionCount; partitionId < offsetCount; partitionId++) - { - nextOffsetsById.remove(partitionId); - } - assert nextOffsetsById.size() <= leadersByPartitionId.size(); + nextOffsetsById.entrySet() + .removeIf( + entry -> !leadersByAssignedId.containsKey(entry.getKey().intValue())); + + assert nextOffsetsById.size() <= leadersByAssignedId.size(); } } @@ -1793,12 +1869,8 @@ private void doProducePartitionsIfNecessary( { if (hasProduceCapability(capabilities)) { - final int partitionCount = leadersByPartitionId.size(); - for (int partitionId = 0; partitionId < partitionCount; partitionId++) - { - doProducePartitionIfNecessary(traceId, partitionId); - } - assert produceStreams.size() >= leadersByPartitionId.size(); + leadersByAssignedId.forEach((k, v) -> doProducePartitionIfNecessary(traceId, k)); + assert produceStreams.size() >= leadersByAssignedId.size(); } } @@ -1806,7 +1878,7 @@ private void doFetchPartitionIfNecessary( long traceId, int partitionId) { - final int leaderId = leadersByPartitionId.get(partitionId); + final int leaderId = leadersByAssignedId.get(partitionId); final long partitionOffset = nextFetchPartitionOffset(partitionId); KafkaUnmergedFetchStream leader = findFetchPartitionLeader(partitionId); @@ -1937,7 +2009,7 @@ private void doProducePartitionIfNecessary( long traceId, int partitionId) { - final int leaderId = leadersByPartitionId.get(partitionId); + final int leaderId = leadersByAssignedId.get(partitionId); KafkaUnmergedProduceStream leader = findProducePartitionLeader(partitionId); @@ -1963,7 +2035,7 @@ private void onProducePartitionLeaderReady( long traceId, long partitionId) { - if (produceStreams.size() == leadersByPartitionId.size()) + if (produceStreams.size() == leadersByAssignedId.size()) { if (!KafkaState.initialOpened(state)) { @@ -1989,7 +2061,7 @@ private void onProducePartitionLeaderError( final KafkaUnmergedProduceStream leader = findProducePartitionLeader(partitionId); assert leader != null; - if (leadersByPartitionId.containsKey(partitionId)) + if (leadersByAssignedId.containsKey(partitionId)) { leader.doProduceInitialBegin(traceId); } @@ -2275,7 +2347,7 @@ private void doDescribeReplyReset( state = KafkaState.closedReply(state); doReset(receiver, merged.routedId, merged.resolvedId, replyId, replySeq, replyAck, replyMax, - traceId, merged.authorization); + traceId, merged.authorization, EMPTY_EXTENSION); } } @@ -2531,7 +2603,271 @@ private void doMetaReplyReset( state = KafkaState.closedReply(state); doReset(receiver, merged.routedId, merged.resolvedId, replyId, replySeq, replyAck, replyMax, - traceId, merged.authorization); + traceId, merged.authorization, EMPTY_EXTENSION); + } + } + + private final class KafkaUnmergedConsumerStream + { + private final KafkaMergedStream merged; + + private long initialId; + private long replyId; + private MessageConsumer receiver = NO_RECEIVER; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + + private KafkaUnmergedConsumerStream( + KafkaMergedStream merged) + { + this.merged = merged; + } + + private void doConsumerInitialBeginIfNecessary( + long traceId) + { + if (!KafkaState.initialOpening(state)) + { + doConsumerInitialBegin(traceId); + } + } + + private void doConsumerInitialBegin( + long traceId) + { + assert state == 0; + + state = KafkaState.openingInitial(state); + + this.initialId = supplyInitialId.applyAsLong(merged.resolvedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.receiver = newStream(this::onConsumerReply, + merged.routedId, merged.resolvedId, initialId, initialSeq, initialAck, initialMax, + traceId, merged.authorization, 0L, + ex -> ex.set((b, o, l) -> kafkaBeginExRW.wrap(b, o, l) + .typeId(kafkaTypeId) + .consumer(c -> c + .groupId(merged.groupId) + .consumerId(merged.consumerId) + .timeout(merged.timeout) + .topic(merged.topic) + .partitionIds(p -> merged.leadersByPartitionId.forEach((k, v) -> + p.item(tp -> tp.partitionId(k)))) + ) + .build() + .sizeof())); + } + + private void doConsumerInitialEndIfNecessary( + long traceId) + { + if (!KafkaState.initialClosed(state)) + { + doConsumerInitialEnd(traceId); + } + } + + private void doConsumerInitialEnd( + long traceId) + { + state = KafkaState.closedInitial(state); + + doEnd(receiver, merged.routedId, merged.resolvedId, initialId, initialSeq, initialAck, initialMax, + traceId, merged.authorization, EMPTY_EXTENSION); + } + + private void doConsumerInitialAbortIfNecessary( + long traceId) + { + if (KafkaState.initialOpening(state) && !KafkaState.initialClosed(state)) + { + doConsumerInitialAbort(traceId); + } + } + + private void doConsumerInitialAbort( + long traceId) + { + state = KafkaState.closedInitial(state); + + doAbort(receiver, merged.routedId, merged.resolvedId, initialId, initialSeq, initialAck, initialMax, + traceId, merged.authorization, EMPTY_EXTENSION); + } + + private void onConsumerReply( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onConsumerReplyBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onConsumerReplyData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onConsumerReplyEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onConsumerReplyAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onConsumerInitialReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onConsumerInitialWindow(window); + break; + default: + break; + } + } + + private void onConsumerReplyBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + + state = KafkaState.openingReply(state); + + doConsumerReplyWindow(traceId, 0, 8192); + } + + private void onConsumerReplyData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final int reserved = data.reserved(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + merged.doMergedCleanup(traceId); + } + else + { + final KafkaDataExFW kafkaDataEx = extension.get(kafkaDataExRO::wrap); + final KafkaConsumerDataExFW kafkaConsumerDataEx = kafkaDataEx.consumer(); + final Array32FW partitions = kafkaConsumerDataEx.partitions(); + final Array32FW assignments = kafkaConsumerDataEx.assignments(); + merged.onTopicConsumerDataChanged(traceId, partitions, assignments); + + doConsumerReplyWindow(traceId, 0, replyMax); + } + } + + private void onConsumerReplyEnd( + EndFW end) + { + final long traceId = end.traceId(); + + state = KafkaState.closedReply(state); + + merged.doMergedReplyBeginIfNecessary(traceId); + merged.doMergedReplyEndIfNecessary(traceId); + + doConsumerInitialEndIfNecessary(traceId); + } + + private void onConsumerReplyAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + + state = KafkaState.closedReply(state); + + merged.doMergedReplyAbortIfNecessary(traceId); + + doConsumerInitialAbortIfNecessary(traceId); + } + + private void onConsumerInitialReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + + state = KafkaState.closedInitial(state); + + merged.doMergedInitialResetIfNecessary(traceId); + + doConsumerReplyResetIfNecessary(traceId); + } + + private void onConsumerInitialWindow( + WindowFW window) + { + if (!KafkaState.initialOpened(state)) + { + final long traceId = window.traceId(); + + state = KafkaState.openedInitial(state); + + merged.doMergedInitialWindow(traceId, 0L); + } + } + + private void doConsumerReplyWindow( + long traceId, + int minReplyNoAck, + int minReplyMax) + { + final long newReplyAck = Math.max(replySeq - minReplyNoAck, replyAck); + + if (newReplyAck > replyAck || minReplyMax > replyMax || !KafkaState.replyOpened(state)) + { + replyAck = newReplyAck; + assert replyAck <= replySeq; + + replyMax = minReplyMax; + + state = KafkaState.openedReply(state); + + doWindow(receiver, merged.routedId, merged.resolvedId, replyId, replySeq, replyAck, replyMax, + traceId, merged.authorization, 0L, merged.replyPad, DEFAULT_MINIMUM); + } + } + + private void doConsumerReplyResetIfNecessary( + long traceId) + { + if (!KafkaState.replyClosed(state)) + { + doConsumerReplyReset(traceId); + } + } + + private void doConsumerReplyReset( + long traceId) + { + state = KafkaState.closedReply(state); + + doReset(receiver, merged.routedId, merged.resolvedId, replyId, replySeq, replyAck, replyMax, + traceId, merged.authorization, EMPTY_EXTENSION); } } @@ -2921,7 +3257,7 @@ private void doFetchReplyReset( state = KafkaState.closedReply(state); doReset(receiver, merged.routedId, merged.resolvedId, replyId, replySeq, replyAck, replyMax, - traceId, merged.authorization); + traceId, merged.authorization, EMPTY_EXTENSION); } private void setFetchFilter( @@ -3089,8 +3425,8 @@ private void doProduceInitialFlush( .typeId(kafkaTypeId) .produce(c -> { - c.partition(kafkaMergedFlushEx.partition()); - c.key(kafkaMergedFlushEx.key()); + c.partition(kafkaMergedFlushEx.fetch().partition()); + c.key(kafkaMergedFlushEx.fetch().key()); }) .build(); @@ -3330,7 +3666,7 @@ private void doProduceReplyReset( state = KafkaState.closedReply(state); doReset(receiver, merged.routedId, merged.resolvedId, replyId, replySeq, replyAck, replyMax, - traceId, merged.authorization); + traceId, merged.authorization, EMPTY_EXTENSION); } } } diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaOffsetFetchTopic.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaOffsetFetchTopic.java new file mode 100644 index 0000000000..f0fbc5f4ec --- /dev/null +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaOffsetFetchTopic.java @@ -0,0 +1,32 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import java.util.List; + +public final class KafkaOffsetFetchTopic +{ + final String topic; + List partitions; + + KafkaOffsetFetchTopic( + String topic, + List partitions) + { + this.topic = topic; + this.partitions = partitions; + } +} diff --git a/runtime/binding-kafka/src/main/moditect/module-info.java b/runtime/binding-kafka/src/main/moditect/module-info.java index 5095971748..1487416b9f 100644 --- a/runtime/binding-kafka/src/main/moditect/module-info.java +++ b/runtime/binding-kafka/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.kafka.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.kafka.internal.KafkaBindingFactorySpi; diff --git a/runtime/binding-kafka/src/main/zilla/protocol.idl b/runtime/binding-kafka/src/main/zilla/protocol.idl index d3267cb430..550d03d9c9 100644 --- a/runtime/binding-kafka/src/main/zilla/protocol.idl +++ b/runtime/binding-kafka/src/main/zilla/protocol.idl @@ -336,7 +336,170 @@ scope protocol struct ProduceResponseTrailer { - int32 thottleTimeMillis; + int32 throttleTimeMillis; + } + } + + scope group + { + struct FindCoordinatorRequest + { + string16 key; + int8 keyType; + } + + struct FindCoordinatorResponse + { + int32 correlationId; + int32 throttleTimeMillis; + int16 errorCode; + string16 errorMessage = null; + int32 nodeId; + string16 host; + int32 port; + } + + struct JoinGroupRequest + { + string16 groupId; + int32 sessionTimeoutMillis; + int32 rebalanceTimeoutMillis; + string16 memberId; + string16 groupInstanceId = null; + string16 protocolType; + int32 protocolCount; + } + + struct ProtocolMetadata + { + string16 name; + uint32 metadataLength; + octets[metadataLength] metadata; + } + + struct RangeProtocol + { + int32 version; + string16 topic; + int32 partitionCount; + } + + struct JoinGroupResponse + { + int32 correlationId; + int32 throttleTimeMillis; + int16 errorCode; + int32 generatedId; + string16 protocolName; + string16 leader; + string16 memberId; + int32 memberCount; + } + + struct MemberMetadata + { + string16 memberId; + string16 groupInstanceId = null; + uint32 length; + octets[length] metadata; + } + + struct SyncGroupRequest + { + string16 groupId; + int32 generatedId; + string16 memberId; + string16 groupInstanceId = null; + int32 assignmentCount; + } + + struct Assignment + { + string16 memberId; + int32 length; + octets[length] value = null; + } + + struct Partition + { + int32 partitionId; + int32 offsetId; + } + + struct SyncGroupResponse + { + int32 correlationId; + int32 throttleTimeMillis; + int16 errorCode; + uint32 assignmentLength; + octets[assignmentLength] assignment; + } + + struct HeartbeatRequest + { + string16 groupId; + int32 generatedId; + string16 memberId; + string16 groupInstanceId = null; + } + + struct HeartbeatResponse + { + int32 correlationId; + int32 throttleTimeMillis; + int16 errorCode; + } + + struct LeaveGroupRequest + { + string16 groupId; + int32 memberCount; + } + + struct LeaveGroupResponse + { + int32 correlationId; + int32 throttleTimeMillis; + int16 errorCode; + int32 memberCount; + } + + struct LeaveMember + { + string16 memberId; + string16 groupInstanceId = null; + } + + struct OffsetFetchRequest + { + string16 groupId; + int32 topicCount; + } + + struct OffsetFetchTopicRequest + { + string16 topic; + int32 partitionsCount; + } + + struct OffsetFetchResponse + { + int32 correlationId; + int32 topicCount; + } + + struct OffsetFetchTopicResponse + { + string16 name; + int32 partitionCount; + } + + struct OffsetFetchPartition + { + int32 partitionIndex; + int64 committedOffset; + string16 metadata = null; + int16 errorCode; } } @@ -374,7 +537,50 @@ scope protocol octets[authBytesLen] authBytes = null; int64 sessionLifetimeMs; } + } + + scope consumer + { + struct ConsumerPartition + { + int32 partitionId; + } + + struct ConsumerTopicPartition + { + string16 topic; + int32 partitionCount; + } + + struct ConsumerSubscriptionUserdata + { + uint32 userdataLength; + octets[userdataLength] userdata; + int32 ownedPartitions; + } + + struct ConsumerAssignmentUserdata + { + uint32 userdataLength; + octets[userdataLength] userdata; + } + + struct ConsumerMetadataTopic + { + string16 name; + } + struct ConsumerSubscriptionMetadata + { + int16 version; + int32 metadataTopicCount; + } + + struct ConsumerAssignmentMetadata + { + int16 version; + int32 metadataTopicCount; + } } } } diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapterTest.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapterTest.java index 05c8731c2f..c1432c0bb3 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapterTest.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaConditionConfigAdapterTest.java @@ -27,6 +27,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaConditionConfig; + public class KafkaConditionConfigAdapterTest { private Jsonb jsonb; @@ -44,23 +46,25 @@ public void shouldReadCondition() { String text = "{" + - "\"topic\": \"test\"" + + "\"topic\": \"test\"," + + "\"groupId\": \"test\"" + "}"; KafkaConditionConfig condition = jsonb.fromJson(text, KafkaConditionConfig.class); assertThat(condition, not(nullValue())); assertThat(condition.topic, equalTo("test")); + assertThat(condition.groupId, equalTo("test")); } @Test public void shouldWriteCondition() { - KafkaConditionConfig condition = new KafkaConditionConfig("test"); + KafkaConditionConfig condition = new KafkaConditionConfig("test", "test"); String text = jsonb.toJson(condition); assertThat(text, not(nullValue())); - assertThat(text, equalTo("{\"topic\":\"test\"}")); + assertThat(text, equalTo("{\"topic\":\"test\",\"groupId\":\"test\"}")); } } diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapterTest.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapterTest.java index 9cbcccbf85..34bf02c8bf 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapterTest.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/config/KafkaOptionsConfigAdapterTest.java @@ -30,6 +30,10 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaOptionsConfig; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaSaslConfig; +import io.aklivity.zilla.runtime.binding.kafka.config.KafkaTopicConfig; + public class KafkaOptionsConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheBootstrapIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheBootstrapIT.java index ac1eadab19..40752fe1a0 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheBootstrapIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheBootstrapIT.java @@ -42,9 +42,7 @@ public class CacheBootstrapIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(16384) + .countersBufferCapacity(16384) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(KAFKA_CACHE_SEGMENT_BYTES, 1 * 1024 * 1024) .configure(KAFKA_CACHE_SEGMENT_INDEX_BYTES, 256 * 1024) diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheConsumerIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheConsumerIT.java new file mode 100644 index 0000000000..b15c860a1c --- /dev/null +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheConsumerIT.java @@ -0,0 +1,75 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.ScriptProperty; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class CacheConsumerIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/kafka/streams/application/group") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/consumer"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(15, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") + .external("app1") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("cache.when.topic.yaml") + @Specification({ + "${app}/partition.assignment/client", + "${net}/partition.assignment/server" + }) + @ScriptProperty("serverAddress \"zilla://streams/app1\"") + public void shouldAssignPartition() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("cache.yaml") + @Specification({ + "${app}/reassign.new.topic/client", + "${net}/reassign.new.topic/server" + }) + @ScriptProperty("serverAddress \"zilla://streams/app1\"") + public void shouldReassignOnUpdatedTopic() throws Exception + { + k3po.finish(); + } + +} diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheDescribeIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheDescribeIT.java index 88f8b3be0f..de23eedc2e 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheDescribeIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheDescribeIT.java @@ -43,9 +43,7 @@ public class CacheDescribeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(KAFKA_CACHE_SERVER_BOOTSTRAP, false) .configure(KAFKA_CACHE_SERVER_RECONNECT_DELAY, 0) .configure(KAFKA_CACHE_SEGMENT_BYTES, 1 * 1024 * 1024) diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheFetchIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheFetchIT.java index 00c7a9756b..b2f9e00260 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheFetchIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheFetchIT.java @@ -51,9 +51,7 @@ public class CacheFetchIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(KAFKA_CACHE_SERVER_BOOTSTRAP, false) .configure(KAFKA_CACHE_SERVER_RECONNECT_DELAY, 0) @@ -466,6 +464,7 @@ public void shouldFetchFilterSync() throws Exception } @Test + @Ignore @Configuration("cache.yaml") @Specification({ "${app}/filter.sync.with.data/client", diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheGroupIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheGroupIT.java new file mode 100644 index 0000000000..136c47c052 --- /dev/null +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheGroupIT.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration.KAFKA_CACHE_SERVER_BOOTSTRAP; +import static io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration.KAFKA_CACHE_SERVER_RECONNECT_DELAY; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.ScriptProperty; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class CacheGroupIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/group"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) + .configure(KAFKA_CACHE_SERVER_BOOTSTRAP, false) + .configure(KAFKA_CACHE_SERVER_RECONNECT_DELAY, 0) + .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") + .external("app1") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("cache.yaml") + @Specification({ + "${app}/rebalance.protocol.highlander/client", + "${app}/rebalance.protocol.highlander/server"}) + @ScriptProperty("serverAddress \"zilla://streams/app1\"") + public void shouldRebalanceLeader() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMergedIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMergedIT.java index fe4ebd9737..3da6fa27ea 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMergedIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMergedIT.java @@ -46,9 +46,7 @@ public class CacheMergedIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(16384) + .countersBufferCapacity(16384) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(KAFKA_CACHE_SERVER_BOOTSTRAP, false) .configure(KAFKA_CACHE_SEGMENT_BYTES, 1 * 1024 * 1024) @@ -403,6 +401,16 @@ public void shouldProduceMergedMessageValuesDynamicHashed() throws Exception k3po.finish(); } + @Test + @Configuration("cache.options.merged.yaml") + @Specification({ + "${app}/merged.produce.message.values.dynamic.hash.key/client", + "${app}/unmerged.produce.message.values.dynamic.hash.key/server"}) + public void shouldProduceMergedMessageValuesDynamicHashKey() throws Exception + { + k3po.finish(); + } + @Test @Configuration("cache.options.merged.yaml") @Specification({ @@ -575,4 +583,34 @@ public void shouldReceiveMessagesWithHeadersSkipManyFilter() throws Exception { k3po.finish(); } + + @Test + @Configuration("cache.options.merged.yaml") + @Specification({ + "${app}/merged.group.fetch.message.value/client", + "${app}/unmerged.group.fetch.message.value/server"}) + public void shouldFetchGroupMessageValue() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("cache.options.merged.yaml") + @Specification({ + "${app}/merged.group.produce.invalid.partition/client", + "${app}/unmerged.group.produce.invalid.partition/server"}) + public void shouldRejectMessageForInvalidPartition() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("cache.options.merged.yaml") + @Specification({ + "${app}/merged.group.produce.message.value/client", + "${app}/unmerged.group.produce.message.value/server"}) + public void shouldProduceMergedMergedMessageValue() throws Exception + { + k3po.finish(); + } } diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMetaIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMetaIT.java index cfdcf7f525..90325d19ab 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMetaIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheMetaIT.java @@ -43,9 +43,7 @@ public class CacheMetaIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(KAFKA_CACHE_SERVER_BOOTSTRAP, false) .configure(KAFKA_CACHE_SERVER_RECONNECT_DELAY, 0) .configure(KAFKA_CACHE_SEGMENT_BYTES, 1 * 1024 * 1024) diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheOffsetFetchIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheOffsetFetchIT.java new file mode 100644 index 0000000000..8bbb8e0d6e --- /dev/null +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheOffsetFetchIT.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration.KAFKA_CACHE_SERVER_BOOTSTRAP; +import static io.aklivity.zilla.runtime.binding.kafka.internal.KafkaConfiguration.KAFKA_CACHE_SERVER_RECONNECT_DELAY; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.ScriptProperty; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class CacheOffsetFetchIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) + .configure(KAFKA_CACHE_SERVER_BOOTSTRAP, false) + .configure(KAFKA_CACHE_SERVER_RECONNECT_DELAY, 0) + .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") + .external("app1") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("cache.yaml") + @Specification({ + "${app}/partition.offset/client", + "${app}/partition.offset/server"}) + @ScriptProperty("serverAddress \"zilla://streams/app1\"") + public void shouldFetchPartitionOffset() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheProduceIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheProduceIT.java index 8aa510437a..0f67e22554 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheProduceIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/CacheProduceIT.java @@ -47,9 +47,7 @@ public class CacheProduceIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(KAFKA_CACHE_SERVER_BOOTSTRAP, false) .configure(KAFKA_CACHE_SERVER_RECONNECT_DELAY, 0) diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeIT.java index 1dcae4d1b1..697dd4324c 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeIT.java @@ -40,9 +40,7 @@ public class ClientDescribeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(KAFKA_CLIENT_DESCRIBE_MAX_AGE_MILLIS, 0) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") .external("net0") diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeSaslIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeSaslIT.java index 6b109acfec..feef221e5c 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeSaslIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientDescribeSaslIT.java @@ -42,9 +42,7 @@ public class ClientDescribeSaslIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(KAFKA_CLIENT_DESCRIBE_MAX_AGE_MILLIS, 0) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") .external("net0") diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchIT.java index abaeb83485..32073041b4 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchIT.java @@ -49,9 +49,7 @@ public class ClientFetchIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchSaslIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchSaslIT.java index c522a5e36f..d9bb13cad2 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchSaslIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientFetchSaslIT.java @@ -42,9 +42,7 @@ public class ClientFetchSaslIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(KAFKA_CLIENT_META_MAX_AGE_MILLIS, 0) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") .external("net0") diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientGroupIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientGroupIT.java new file mode 100644 index 0000000000..33670fffc3 --- /dev/null +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientGroupIT.java @@ -0,0 +1,149 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class ClientGroupIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/group"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(15, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/client.sent.write.abort.before.coordinator.response/client", + "${net}/client.sent.write.abort.before.coordinator.response/server"}) + public void shouldHandleClientSentWriteAbortBeforeCoordinatorResponse() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/rebalance.protocol.highlander/client", + "${net}/rebalance.protocol.highlander/server"}) + public void shouldLeaveGroupOnGroupRebalanceError() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/leader/client", + "${net}/coordinator.not.available/server"}) + public void shouldHandleCoordinatorNotAvailableError() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/leader/client", + "${net}/coordinator.reject.invalid.consumer/server"}) + public void shouldRejectInvalidConsumer() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/leader/client", + "${net}/rebalance.protocol.highlander.unknown.member.id/server"}) + public void shouldRebalanceProtocolHighlanderUnknownMemberId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/rebalance.protocol.highlander.migrate.leader/client", + "${net}/rebalance.protocol.highlander.migrate.leader/server"}) + public void shouldRebalanceProtocolHighlanderMigrateLeader() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/rebalance.protocol.highlander.migrate.leader.in.parallel/client", + "${net}/rebalance.protocol.highlander.migrate.leader.in.parallel/server"}) + public void shouldRebalanceProtocolHighlanderMigrateLeaderInParallel() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/rebalance.protocol.unknown/client", + "${net}/rebalance.protocol.unknown/server"}) + public void shouldRejectSecondStreamOnUnknownProtocol() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/rebalance.sync.group/client", + "${net}/rebalance.sync.group/server"}) + public void shouldHandleRebalanceSyncGroup() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/ignore.heartbeat.before.handshake/client", + "${net}/ignore.heartbeat.before.handshake/server"}) + public void shouldIgnoreHeartbeatBeforeHandshakeComplete() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientGroupSaslIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientGroupSaslIT.java new file mode 100644 index 0000000000..0a7d42c17c --- /dev/null +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientGroupSaslIT.java @@ -0,0 +1,61 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class ClientGroupSaslIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", + "io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/group"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(15, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + + @Test + @Configuration("client.options.sasl.plain.yaml") + @Specification({ + "${app}/leader/client", + "${net}/leader/server"}) + public void shouldBecomeLeader() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMergedIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMergedIT.java index 8844ff1b7f..8ae2d6fd51 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMergedIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMergedIT.java @@ -46,9 +46,7 @@ public class ClientMergedIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configure(KAFKA_CLIENT_META_MAX_AGE_MILLIS, 1000) .configure(KAFKA_CLIENT_PRODUCE_MAX_BYTES, 116) diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaIT.java index 10a77e5b32..ddd5b9fe47 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaIT.java @@ -40,9 +40,7 @@ public class ClientMetaIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(KAFKA_CLIENT_META_MAX_AGE_MILLIS, 0) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") .external("net0") diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaSaslIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaSaslIT.java index c3ff4d68d4..75501b13a4 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaSaslIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientMetaSaslIT.java @@ -42,9 +42,7 @@ public class ClientMetaSaslIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(KAFKA_CLIENT_META_MAX_AGE_MILLIS, 0) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") .external("net0") diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientOffsetFetchIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientOffsetFetchIT.java new file mode 100644 index 0000000000..fd2bafaf55 --- /dev/null +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientOffsetFetchIT.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.kafka.internal.stream; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class ClientOffsetFetchIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/kafka/streams/network/offset.fetch.v0") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(15, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/partition.offset/client", + "${net}/topic.offset.info/server"}) + public void shouldFetchPartitionLastCommittedOffset() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java index 45cb9481c6..5a22d21243 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java @@ -44,9 +44,7 @@ public class ClientProduceIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceSaslIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceSaslIT.java index 6a44330a41..818f5d7c47 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceSaslIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceSaslIT.java @@ -43,9 +43,7 @@ public class ClientProduceSaslIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configurationRoot("io/aklivity/zilla/specs/binding/kafka/config") diff --git a/incubator/binding-mqtt-kafka/COPYRIGHT b/runtime/binding-mqtt-kafka/COPYRIGHT similarity index 100% rename from incubator/binding-mqtt-kafka/COPYRIGHT rename to runtime/binding-mqtt-kafka/COPYRIGHT diff --git a/incubator/binding-mqtt-kafka/LICENSE b/runtime/binding-mqtt-kafka/LICENSE similarity index 100% rename from incubator/binding-mqtt-kafka/LICENSE rename to runtime/binding-mqtt-kafka/LICENSE diff --git a/runtime/binding-mqtt-kafka/NOTICE b/runtime/binding-mqtt-kafka/NOTICE new file mode 100644 index 0000000000..9024d8926d --- /dev/null +++ b/runtime/binding-mqtt-kafka/NOTICE @@ -0,0 +1,13 @@ +Licensed under the Aklivity Community License (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + https://www.aklivity.io/aklivity-community-license/ + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +WARRANTIES OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +This project includes: + diff --git a/incubator/binding-mqtt-kafka/NOTICE.template b/runtime/binding-mqtt-kafka/NOTICE.template similarity index 100% rename from incubator/binding-mqtt-kafka/NOTICE.template rename to runtime/binding-mqtt-kafka/NOTICE.template diff --git a/incubator/binding-mqtt-kafka/mvnw b/runtime/binding-mqtt-kafka/mvnw similarity index 100% rename from incubator/binding-mqtt-kafka/mvnw rename to runtime/binding-mqtt-kafka/mvnw diff --git a/incubator/binding-mqtt-kafka/mvnw.cmd b/runtime/binding-mqtt-kafka/mvnw.cmd similarity index 100% rename from incubator/binding-mqtt-kafka/mvnw.cmd rename to runtime/binding-mqtt-kafka/mvnw.cmd diff --git a/runtime/binding-mqtt-kafka/pom.xml b/runtime/binding-mqtt-kafka/pom.xml new file mode 100644 index 0000000000..7a383c0847 --- /dev/null +++ b/runtime/binding-mqtt-kafka/pom.xml @@ -0,0 +1,245 @@ + + + + 4.0.0 + + io.aklivity.zilla + runtime + 0.9.52 + ../pom.xml + + + binding-mqtt-kafka + zilla::runtime::binding-mqtt-kafka + + + + Aklivity Community License Agreement + https://www.aklivity.io/aklivity-community-license/ + repo + + + + + 11 + 11 + 0.90 + 0 + + + + + ${project.groupId} + binding-mqtt-kafka.spec + ${project.version} + provided + + + ${project.groupId} + engine + ${project.version} + provided + + + ${project.groupId} + engine + test-jar + ${project.version} + test + + + junit + junit + test + + + org.hamcrest + hamcrest + test + + + com.vtence.hamcrest + hamcrest-jpa + test + + + com.github.npathai + hamcrest-optional + test + + + org.mockito + mockito-core + test + + + org.kaazing + k3po.junit + test + + + org.kaazing + k3po.lang + test + + + org.openjdk.jmh + jmh-core + test + + + org.openjdk.jmh + jmh-generator-annprocess + test + + + + + + + org.jasig.maven + maven-notice-plugin + + + ${project.groupId} + flyweight-maven-plugin + ${project.version} + + core mqtt kafka internal + io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types + + + + + generate + + + + + + com.mycila + license-maven-plugin + + + maven-checkstyle-plugin + + + maven-dependency-plugin + + + process-resources + + unpack + + + + + ${project.groupId} + binding-mqtt-kafka.spec + + + ^\Qio/aklivity/zilla/specs/binding/mqtt/kafka/\E + io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/ + + + + + io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json + ${project.build.directory}/classes + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.moditect + moditect-maven-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + org.kaazing + k3po-maven-plugin + + + ${project.groupId} + engine + ${project.version} + test-jar + + + ${project.groupId} + engine + ${project.version} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.jacoco + jacoco-maven-plugin + + + io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/types/**/*.class + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + ${jacoco.coverage.ratio} + + + CLASS + MISSEDCOUNT + ${jacoco.missed.count} + + + + + + + + io.gatling + maven-shade-plugin + + + + org.agrona:agrona + io.aklivity.zilla:engine + org.openjdk.jmh:jmh-core + net.sf.jopt-simple:jopt-simple + org.apache.commons:commons-math3 + commons-cli:commons-cli + com.github.biboudis:jmh-profilers + + + + + + + diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfig.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/config/MqttKafkaConditionConfig.java similarity index 92% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfig.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/config/MqttKafkaConditionConfig.java index 9ba2880b17..8df04215ba 100644 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfig.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/config/MqttKafkaConditionConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.mqtt.kafka.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/InstanceId.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/InstanceId.java new file mode 100644 index 0000000000..fcb5bc86ca --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/InstanceId.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal; + +import java.util.function.Supplier; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; + + +public class InstanceId +{ + private final Supplier supplyInstanceId; + private volatile String16FW instanceId; + + InstanceId( + Supplier supplyInstanceId) + { + this.supplyInstanceId = supplyInstanceId; + regenerate(); + } + + public void regenerate() + { + instanceId = new String16FW(supplyInstanceId.get()); + } + + public String16FW instanceId() + { + return instanceId; + } +} diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBinding.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBinding.java similarity index 88% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBinding.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBinding.java index 1bddbf2258..e6c756481c 100644 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBinding.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBinding.java @@ -24,10 +24,12 @@ public class MqttKafkaBinding implements Binding public static final String NAME = "mqtt-kafka"; private final MqttKafkaConfiguration config; + private final InstanceId instanceId; MqttKafkaBinding( MqttKafkaConfiguration config) { + this.instanceId = new InstanceId(config.instanceId()); this.config = config; } @@ -47,6 +49,7 @@ public URL type() public MqttKafkaBindingContext supply( EngineContext context) { - return new MqttKafkaBindingContext(config, context); + return new MqttKafkaBindingContext(config, context, instanceId); } + } diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingContext.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingContext.java similarity index 95% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingContext.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingContext.java index 3a613eff0c..6ea46f8dc3 100644 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingContext.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingContext.java @@ -33,9 +33,10 @@ public class MqttKafkaBindingContext implements BindingContext MqttKafkaBindingContext( MqttKafkaConfiguration config, - EngineContext context) + EngineContext context, + InstanceId instanceId) { - this.factories = singletonMap(PROXY, new MqttKafkaProxyFactory(config, context)); + this.factories = singletonMap(PROXY, new MqttKafkaProxyFactory(config, context, instanceId)); } @Override diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingFactorySpi.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingFactorySpi.java similarity index 100% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingFactorySpi.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaBindingFactorySpi.java diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfiguration.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfiguration.java new file mode 100644 index 0000000000..2dc397183d --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfiguration.java @@ -0,0 +1,199 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal; + +import static java.time.Instant.now; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.UUID; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +import org.agrona.LangUtil; + +import io.aklivity.zilla.runtime.engine.Configuration; + +public class MqttKafkaConfiguration extends Configuration +{ + private static final ConfigurationDef MQTT_KAFKA_CONFIG; + public static final PropertyDef SESSION_ID; + public static final PropertyDef WILL_ID; + public static final PropertyDef LIFETIME_ID; + public static final PropertyDef INSTANCE_ID; + public static final PropertyDef TIME; + public static final BooleanPropertyDef WILL_AVAILABLE; + public static final IntPropertyDef WILL_STREAM_RECONNECT_DELAY; + + static + { + final ConfigurationDef config = new ConfigurationDef("zilla.binding.mqtt.kafka"); + SESSION_ID = config.property(StringSupplier.class, "session.id", + MqttKafkaConfiguration::decodeStringSupplier, MqttKafkaConfiguration::defaultSessionId); + WILL_ID = config.property(StringSupplier.class, "will.id", + MqttKafkaConfiguration::decodeStringSupplier, MqttKafkaConfiguration::defaultWillId); + LIFETIME_ID = config.property(StringSupplier.class, "lifetime.id", + MqttKafkaConfiguration::decodeStringSupplier, MqttKafkaConfiguration::defaultLifetimeId); + INSTANCE_ID = config.property(StringSupplier.class, "instance.id", + MqttKafkaConfiguration::decodeStringSupplier, MqttKafkaConfiguration::defaultInstanceId); + TIME = config.property(LongSupplier.class, "time", + MqttKafkaConfiguration::decodeLongSupplier, MqttKafkaConfiguration::defaultTime); + WILL_AVAILABLE = config.property("will.available", true); + WILL_STREAM_RECONNECT_DELAY = config.property("will.stream.reconnect", 2); + MQTT_KAFKA_CONFIG = config; + } + + public MqttKafkaConfiguration( + Configuration config) + { + super(MQTT_KAFKA_CONFIG, config); + } + + @FunctionalInterface + public interface StringSupplier extends Supplier + { + } + + public Supplier sessionId() + { + return SESSION_ID.get(this); + } + + public Supplier willId() + { + return WILL_ID.get(this); + } + + public Supplier lifetimeId() + { + return LIFETIME_ID.get(this); + } + + public Supplier instanceId() + { + return INSTANCE_ID.get(this); + } + + public LongSupplier time() + { + return TIME.get(this); + } + + public boolean willAvailable() + { + return WILL_AVAILABLE.get(this); + } + + public int willStreamReconnectDelay() + { + return WILL_STREAM_RECONNECT_DELAY.getAsInt(this); + } + + private static StringSupplier decodeStringSupplier( + String fullyQualifiedMethodName) + { + StringSupplier supplier = null; + + try + { + MethodType signature = MethodType.methodType(String.class); + String[] parts = fullyQualifiedMethodName.split("::"); + Class ownerClass = Class.forName(parts[0]); + String methodName = parts[1]; + MethodHandle method = MethodHandles.publicLookup().findStatic(ownerClass, methodName, signature); + supplier = () -> + { + String value = null; + try + { + value = (String) method.invoke(); + } + catch (Throwable ex) + { + LangUtil.rethrowUnchecked(ex); + } + + return value; + }; + } + catch (Throwable ex) + { + LangUtil.rethrowUnchecked(ex); + } + + return supplier; + } + + private static LongSupplier decodeLongSupplier( + String fullyQualifiedMethodName) + { + LongSupplier supplier = null; + + try + { + MethodType signature = MethodType.methodType(long.class); + String[] parts = fullyQualifiedMethodName.split("::"); + Class ownerClass = Class.forName(parts[0]); + String methodName = parts[1]; + MethodHandle method = MethodHandles.publicLookup().findStatic(ownerClass, methodName, signature); + supplier = () -> + { + long value = 0; + try + { + value = (long) method.invoke(); + } + catch (Throwable ex) + { + LangUtil.rethrowUnchecked(ex); + } + + return value; + }; + } + catch (Throwable ex) + { + LangUtil.rethrowUnchecked(ex); + } + + return supplier; + } + + private static String defaultInstanceId() + { + return String.format("%s-%s", "zilla", UUID.randomUUID()); + } + + private static String defaultSessionId() + { + return String.format("%s-%s", "zilla", UUID.randomUUID()); + } + + private static String defaultWillId() + { + return String.format("%s", UUID.randomUUID()); + } + + private static String defaultLifetimeId() + { + return String.format("%s", UUID.randomUUID()); + } + + private static long defaultTime() + { + return now().toEpochMilli(); + } +} diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java new file mode 100644 index 0000000000..53b57260ff --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java @@ -0,0 +1,67 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config; + +import static java.util.stream.Collectors.toList; + +import java.util.List; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionFactory; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; +import io.aklivity.zilla.runtime.engine.config.BindingConfig; +import io.aklivity.zilla.runtime.engine.config.KindConfig; + +public class MqttKafkaBindingConfig +{ + public final long id; + public final KindConfig kind; + public final MqttKafkaOptionsConfig options; + public final List routes; + + public MqttKafkaSessionFactory.KafkaSignalStream willProxy; + + public MqttKafkaBindingConfig( + BindingConfig binding) + { + this.id = binding.id; + this.kind = binding.kind; + this.options = (MqttKafkaOptionsConfig) binding.options; + this.routes = binding.routes.stream().map(MqttKafkaRouteConfig::new).collect(toList()); + } + + public MqttKafkaRouteConfig resolve( + long authorization) + { + return routes.stream() + .filter(r -> r.authorized(authorization)) + .findFirst() + .orElse(null); + } + + public String16FW messagesTopic() + { + return options.topics.messages; + } + + public String16FW sessionsTopic() + { + return options.topics.sessions; + } + + public String16FW retainedTopic() + { + return options.topics.retained; + } +} diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapter.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapter.java similarity index 95% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapter.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapter.java index 22fb457072..ca3ed0595c 100644 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapter.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapter.java @@ -19,6 +19,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.config.MqttKafkaConditionConfig; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaHeaderHelper.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaHeaderHelper.java similarity index 82% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaHeaderHelper.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaHeaderHelper.java index 48bd6128cf..3883420442 100644 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaHeaderHelper.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaHeaderHelper.java @@ -28,7 +28,8 @@ public class MqttKafkaHeaderHelper { - private static final String KAFKA_TOPIC_HEADER_NAME = "zilla:topic"; + private static final String KAFKA_FILTER_HEADER_NAME = "zilla:filter"; + private static final String KAFKA_REPLY_FILTER_HEADER_NAME = "zilla:reply-filter"; private static final String KAFKA_LOCAL_HEADER_NAME = "zilla:local"; @@ -39,44 +40,53 @@ public class MqttKafkaHeaderHelper private static final String KAFKA_FORMAT_HEADER_NAME = "zilla:format"; private static final String KAFKA_REPLY_TO_HEADER_NAME = "zilla:reply-to"; + private static final String KAFKA_REPLY_KEY_HEADER_NAME = "zilla:reply-key"; private static final String KAFKA_CORRELATION_ID_HEADER_NAME = "zilla:correlation-id"; - public final OctetsFW kafkaTopicHeaderName; + public final OctetsFW kafkaFilterHeaderName; + public final OctetsFW kafkaReplyFilterHeaderName; public final OctetsFW kafkaLocalHeaderName; public final OctetsFW kafkaTimeoutHeaderName; public final OctetsFW kafkaContentTypeHeaderName; public final OctetsFW kafkaFormatHeaderName; public final OctetsFW kafkaReplyToHeaderName; + public final OctetsFW kafkaReplyKeyHeaderName; public final OctetsFW kafkaCorrelationHeaderName; private final Map> visitors; public final OctetsFW contentTypeRO = new OctetsFW(); public final OctetsFW replyToRO = new OctetsFW(); + public final OctetsFW replyKeyRO = new OctetsFW(); public int timeout; public OctetsFW contentType; public String format; public OctetsFW replyTo; + public OctetsFW replyKey; public OctetsFW correlation; public IntArrayList userPropertiesOffsets; public MqttKafkaHeaderHelper() { - kafkaTopicHeaderName = stringToOctets(KAFKA_TOPIC_HEADER_NAME); + kafkaFilterHeaderName = stringToOctets(KAFKA_FILTER_HEADER_NAME); + kafkaReplyFilterHeaderName = stringToOctets(KAFKA_REPLY_FILTER_HEADER_NAME); kafkaLocalHeaderName = stringToOctets(KAFKA_LOCAL_HEADER_NAME); kafkaTimeoutHeaderName = stringToOctets(KAFKA_TIMEOUT_HEADER_NAME); kafkaContentTypeHeaderName = stringToOctets(KAFKA_CONTENT_TYPE_HEADER_NAME); kafkaFormatHeaderName = stringToOctets(KAFKA_FORMAT_HEADER_NAME); kafkaReplyToHeaderName = stringToOctets(KAFKA_REPLY_TO_HEADER_NAME); + kafkaReplyKeyHeaderName = stringToOctets(KAFKA_REPLY_KEY_HEADER_NAME); kafkaCorrelationHeaderName = stringToOctets(KAFKA_CORRELATION_ID_HEADER_NAME); visitors = new HashMap<>(); - visitors.put(kafkaTopicHeaderName, this::skip); + visitors.put(kafkaFilterHeaderName, this::skip); + visitors.put(kafkaReplyFilterHeaderName, this::skip); visitors.put(kafkaLocalHeaderName, this::skip); visitors.put(kafkaTimeoutHeaderName, this::visitTimeout); visitors.put(kafkaContentTypeHeaderName, this::visitContentType); visitors.put(kafkaFormatHeaderName, this::visitFormat); visitors.put(kafkaReplyToHeaderName, this::visitReplyTo); + visitors.put(kafkaReplyKeyHeaderName, this::visitReplyKey); visitors.put(kafkaCorrelationHeaderName, this::visitCorrelationId); } @@ -133,6 +143,12 @@ private void visitReplyTo( replyTo = replyToRO.wrap(value.buffer(), value.offset(), value.limit()); } + private void visitReplyKey( + OctetsFW value) + { + replyKey = replyKeyRO.wrap(value.buffer(), value.offset(), value.limit()); + } + private void visitCorrelationId( OctetsFW value) { diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfig.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfig.java new file mode 100644 index 0000000000..6b4a3e5225 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfig.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config; + +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public class MqttKafkaOptionsConfig extends OptionsConfig +{ + public final MqttKafkaTopicsConfig topics; + public final String serverRef; + + public MqttKafkaOptionsConfig( + MqttKafkaTopicsConfig topics, + String serverRef) + { + this.topics = topics; + this.serverRef = serverRef; + } +} diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfigAdapter.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfigAdapter.java new file mode 100644 index 0000000000..2b1b665593 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfigAdapter.java @@ -0,0 +1,105 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.bind.adapter.JsonbAdapter; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaBinding; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; + +public class MqttKafkaOptionsConfigAdapter implements OptionsConfigAdapterSpi, JsonbAdapter +{ + private static final String TOPICS_NAME = "topics"; + private static final String SERVER_NAME = "server"; + private static final String SESSIONS_NAME = "sessions"; + private static final String MESSAGES_NAME = "messages"; + private static final String RETAINED_NAME = "retained"; + + @Override + public Kind kind() + { + return Kind.BINDING; + } + + @Override + public String type() + { + return MqttKafkaBinding.NAME; + } + + @Override + public JsonObject adaptToJson( + OptionsConfig options) + { + MqttKafkaOptionsConfig mqttKafkaOptions = (MqttKafkaOptionsConfig) options; + + JsonObjectBuilder object = Json.createObjectBuilder(); + + String serverRef = mqttKafkaOptions.serverRef; + MqttKafkaTopicsConfig topics = mqttKafkaOptions.topics; + + if (serverRef != null) + { + object.add(SERVER_NAME, serverRef); + } + if (topics != null) + { + JsonObjectBuilder newTopics = Json.createObjectBuilder(); + String16FW sessions = topics.sessions; + if (sessions != null) + { + newTopics.add(SESSIONS_NAME, sessions.asString()); + } + + String16FW messages = topics.messages; + if (messages != null) + { + newTopics.add(MESSAGES_NAME, messages.asString()); + } + + String16FW retained = topics.retained; + if (retained != null) + { + newTopics.add(RETAINED_NAME, retained.asString()); + } + + object.add(TOPICS_NAME, newTopics); + } + + return object.build(); + } + + @Override + public OptionsConfig adaptFromJson( + JsonObject object) + { + JsonObject topics = object.getJsonObject(TOPICS_NAME); + String server = object.getString(SERVER_NAME, null); + + String16FW newSessions = new String16FW(topics.getString(SESSIONS_NAME)); + String16FW newMessages = new String16FW(topics.getString(MESSAGES_NAME)); + String16FW newRetained = new String16FW(topics.getString(RETAINED_NAME)); + + MqttKafkaTopicsConfig newTopics = new MqttKafkaTopicsConfig(newSessions, newMessages, newRetained); + + return new MqttKafkaOptionsConfig(newTopics, server); + } +} diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaRouteConfig.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaRouteConfig.java similarity index 100% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaRouteConfig.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaRouteConfig.java diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaTopicsConfig.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaTopicsConfig.java new file mode 100644 index 0000000000..9a5c5066e1 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaTopicsConfig.java @@ -0,0 +1,36 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config; + + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; + +public class MqttKafkaTopicsConfig +{ + public final String16FW sessions; + public final String16FW messages; + public final String16FW retained; + + public MqttKafkaTopicsConfig( + String16FW sessions, + String16FW messages, + String16FW retained) + { + this.sessions = sessions; + this.messages = messages; + this.retained = retained; + } +} + diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java similarity index 81% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java index d303424373..08e8367cbf 100644 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java @@ -14,10 +14,13 @@ */ package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.WILL_STREAM_RECONNECT_DELAY; + import org.agrona.DirectBuffer; import org.agrona.collections.Int2ObjectHashMap; import org.agrona.collections.Long2ObjectHashMap; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.InstanceId; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; @@ -37,15 +40,16 @@ public class MqttKafkaProxyFactory implements MqttKafkaStreamFactory private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); private final int mqttTypeId; - private final Int2ObjectHashMap factories; + private final Int2ObjectHashMap factories; private final Long2ObjectHashMap bindings; public MqttKafkaProxyFactory( MqttKafkaConfiguration config, - EngineContext context) + EngineContext context, + InstanceId instanceId) { final Long2ObjectHashMap bindings = new Long2ObjectHashMap<>(); - final Int2ObjectHashMap factories = new Int2ObjectHashMap<>(); + final Int2ObjectHashMap factories = new Int2ObjectHashMap<>(); final MqttKafkaPublishFactory publishFactory = new MqttKafkaPublishFactory( config, context, bindings::get); @@ -53,12 +57,12 @@ public MqttKafkaProxyFactory( final MqttKafkaSubscribeFactory subscribeFactory = new MqttKafkaSubscribeFactory( config, context, bindings::get); - // final MqttKafkaSessionFactory sessionFactory = new MqttKafkaSessionFactory( - // config, context, bindings::get); + final MqttKafkaSessionFactory sessionFactory = new MqttKafkaSessionFactory( + config, context, instanceId, bindings::get, WILL_STREAM_RECONNECT_DELAY); factories.put(MqttBeginExFW.KIND_PUBLISH, publishFactory); factories.put(MqttBeginExFW.KIND_SUBSCRIBE, subscribeFactory); - // factories.put(MqttBeginExFW.KIND_SESSION, sessionFactory); + factories.put(MqttBeginExFW.KIND_SESSION, sessionFactory); this.mqttTypeId = context.supplyTypeId(MQTT_TYPE_NAME); this.factories = factories; @@ -71,12 +75,15 @@ public void attach( { MqttKafkaBindingConfig kafkaBinding = new MqttKafkaBindingConfig(binding); bindings.put(binding.id, kafkaBinding); + + factories.values().forEach(streamFactory -> streamFactory.onAttached(binding.id)); } @Override public void detach( long bindingId) { + factories.values().forEach(streamFactory -> streamFactory.onDetached(bindingId)); bindings.remove(bindingId); } @@ -93,7 +100,7 @@ public MessageConsumer newStream( final ExtensionFW beginEx = extension.get(extensionRO::tryWrap); assert beginEx != null; final int typeId = beginEx.typeId(); - assert beginEx != null && typeId == mqttTypeId; + assert typeId == mqttTypeId; MessageConsumer newStream = null; diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java new file mode 100644 index 0000000000..258fa73218 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java @@ -0,0 +1,1574 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; + +import static java.time.Instant.now; + +import java.nio.ByteOrder; +import java.util.function.LongFunction; +import java.util.function.LongUnaryOperator; + +import org.agrona.BitUtil; +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaHeaderHelper; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaAckMode; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaCapabilities; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaHeaderFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaKeyFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormatFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPublishFlags; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttPublishBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttPublishDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; + +public class MqttKafkaPublishFactory implements MqttKafkaStreamFactory +{ + private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(new UnsafeBuffer(new byte[0]), 0, 0); + private static final KafkaAckMode KAFKA_DEFAULT_ACK_MODE = KafkaAckMode.LEADER_ONLY; + private static final String KAFKA_TYPE_NAME = "kafka"; + private static final byte SLASH_BYTE = (byte) '/'; + + private final OctetsFW emptyRO = new OctetsFW().wrap(new UnsafeBuffer(0L, 0), 0, 0); + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final AbortFW abortRO = new AbortFW(); + private final FlushFW flushRO = new FlushFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + + private final WindowFW windowRO = new WindowFW(); + private final ResetFW resetRO = new ResetFW(); + + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + + private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); + private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); + + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); + private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); + private final Array32FW.Builder kafkaHeadersRW = + new Array32FW.Builder<>(new KafkaHeaderFW.Builder(), new KafkaHeaderFW()); + + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final MutableDirectBuffer kafkaHeadersBuffer; + private final BindingHandler streamFactory; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final MqttKafkaHeaderHelper helper; + private final int kafkaTypeId; + private final LongFunction supplyBinding; + private final String16FW binaryFormat; + private final String16FW textFormat; + + public MqttKafkaPublishFactory( + MqttKafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding) + { + this.kafkaTypeId = context.supplyTypeId(KAFKA_TYPE_NAME); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.kafkaHeadersBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.helper = new MqttKafkaHeaderHelper(); + this.streamFactory = context.streamFactory(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyBinding = supplyBinding; + this.binaryFormat = new String16FW(MqttPayloadFormat.BINARY.name()); + this.textFormat = new String16FW(MqttPayloadFormat.TEXT.name()); + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer mqtt) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + + final MqttKafkaBindingConfig binding = supplyBinding.apply(routedId); + + final MqttKafkaRouteConfig resolved = binding != null ? binding.resolve(authorization) : null; + MessageConsumer newStream = null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + newStream = new MqttPublishProxy(mqtt, originId, routedId, initialId, resolvedId, + binding.messagesTopic(), binding.retainedTopic())::onMqttMessage; + } + + return newStream; + } + + private final class MqttPublishProxy + { + private final MessageConsumer mqtt; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final KafkaMessagesProxy messages; + private final KafkaRetainedProxy retained; + private final String16FW kafkaMessagesTopic; + private final String16FW kafkaRetainedTopic; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaKeyFW key; + + private Array32FW topicNameHeaders; + private OctetsFW clientIdOctets; + private boolean retainAvailable; + + private MqttPublishProxy( + MessageConsumer mqtt, + long originId, + long routedId, + long initialId, + long resolvedId, + String16FW kafkaMessagesTopic, + String16FW kafkaRetainedTopic) + { + this.mqtt = mqtt; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.messages = new KafkaMessagesProxy(originId, resolvedId, this); + this.retained = new KafkaRetainedProxy(originId, resolvedId, this); + this.kafkaMessagesTopic = kafkaMessagesTopic; + this.kafkaRetainedTopic = kafkaRetainedTopic; + } + + private void onMqttMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onMqttBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onMqttData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onMqttEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onMqttAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onMqttReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onMqttWindow(window); + break; + } + } + + private void onMqttBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + state = MqttKafkaState.openingInitial(state); + + assert initialAck <= initialSeq; + + final OctetsFW extension = begin.extension(); + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + + assert mqttBeginEx.kind() == MqttBeginExFW.KIND_PUBLISH; + final MqttPublishBeginExFW mqttPublishBeginEx = mqttBeginEx.publish(); + String topicName = mqttPublishBeginEx.topic().asString(); + assert topicName != null; + + + final String16FW clientId = mqttPublishBeginEx.clientId(); + final MutableDirectBuffer clientIdBuffer = new UnsafeBuffer(new byte[clientId.sizeof() + 2]); + this.clientIdOctets = new OctetsFW.Builder().wrap(clientIdBuffer, 0, clientIdBuffer.capacity()) + .set(clientId.value(), 0, mqttPublishBeginEx.clientId().length()).build(); + + String[] topicHeaders = topicName.split("/"); + final OctetsFW[] topicNameHeaders = new OctetsFW[topicHeaders.length]; + + final int topicNameHeadersBufferSize = topicName.length() - (topicNameHeaders.length - 1) + + topicNameHeaders.length * 2 + BitUtil.SIZE_OF_INT + BitUtil.SIZE_OF_INT; //Array32FW count, length + final MutableDirectBuffer topicNameHeadersBuffer = new UnsafeBuffer(new byte[topicNameHeadersBufferSize]); + + final Array32FW.Builder topicNameHeadersRW = + new Array32FW.Builder<>(new String16FW.Builder(), new String16FW()); + topicNameHeadersRW.wrap(topicNameHeadersBuffer, 0, topicNameHeadersBuffer.capacity()); + + for (int i = 0; i < topicHeaders.length; i++) + { + String16FW topicHeader = new String16FW(topicHeaders[i]); + topicNameHeadersRW.item(h -> h.set(topicHeader)); + } + this.topicNameHeaders = topicNameHeadersRW.build(); + + + final DirectBuffer topicNameBuffer = mqttPublishBeginEx.topic().value(); + final MutableDirectBuffer keyBuffer = new UnsafeBuffer(new byte[topicNameBuffer.capacity() + 4]); + key = new KafkaKeyFW.Builder() + .wrap(keyBuffer, 0, keyBuffer.capacity()) + .length(topicNameBuffer.capacity()) + .value(topicNameBuffer, 0, topicNameBuffer.capacity()) + .build(); + + messages.doKafkaBegin(traceId, authorization, affinity, kafkaMessagesTopic); + this.retainAvailable = (mqttPublishBeginEx.flags() & 1 << MqttPublishFlags.RETAIN.value()) != 0; + if (retainAvailable) + { + retained.doKafkaBegin(traceId, authorization, affinity, kafkaRetainedTopic); + } + } + + private void onMqttData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + final int flags = data.flags(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + Flyweight kafkaDataEx = emptyRO; + MqttDataExFW mqttDataEx = null; + if (extension.sizeof() > 0) + { + mqttDataEx = extension.get(mqttDataExRO::tryWrap); + } + + assert mqttDataEx.kind() == MqttDataExFW.KIND_PUBLISH; + final MqttPublishDataExFW mqttPublishDataEx = mqttDataEx.publish(); + kafkaHeadersRW.wrap(kafkaHeadersBuffer, 0, kafkaHeadersBuffer.capacity()); + + topicNameHeaders.forEach(th -> addHeader(helper.kafkaFilterHeaderName, th)); + + addHeader(helper.kafkaLocalHeaderName, clientIdOctets); + + if (mqttPublishDataEx.expiryInterval() != -1) + { + final MutableDirectBuffer expiryBuffer = new UnsafeBuffer(new byte[4]); + expiryBuffer.putInt(0, mqttPublishDataEx.expiryInterval() * 1000, ByteOrder.BIG_ENDIAN); + kafkaHeadersRW.item(h -> + { + h.nameLen(helper.kafkaTimeoutHeaderName.sizeof()); + h.name(helper.kafkaTimeoutHeaderName); + h.valueLen(4); + h.value(expiryBuffer, 0, expiryBuffer.capacity()); + }); + } + + if (mqttPublishDataEx.contentType().length() != -1) + { + addHeader(helper.kafkaContentTypeHeaderName, mqttPublishDataEx.contentType()); + } + + if (payload.sizeof() != 0 && mqttPublishDataEx.format() != null) + { + addHeader(helper.kafkaFormatHeaderName, mqttPublishDataEx.format()); + } + + if (mqttPublishDataEx.responseTopic().length() != -1) + { + final String16FW responseTopic = mqttPublishDataEx.responseTopic(); + addHeader(helper.kafkaReplyToHeaderName, kafkaMessagesTopic); + addHeader(helper.kafkaReplyKeyHeaderName, responseTopic); + + addFiltersHeader(responseTopic); + } + + if (mqttPublishDataEx.correlation().bytes() != null) + { + addHeader(helper.kafkaCorrelationHeaderName, mqttPublishDataEx.correlation().bytes()); + } + + mqttPublishDataEx.properties().forEach(property -> + addHeader(property.key(), property.value())); + + final int deferred = mqttPublishDataEx.deferred(); + kafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(deferred) + .timestamp(now().toEpochMilli()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.set(key)) + .headers(kafkaHeadersRW.build())) + .build(); + + messages.doKafkaData(traceId, authorization, budgetId, reserved, flags, payload, kafkaDataEx); + + if (retainAvailable) + { + if ((mqttPublishDataEx.flags() & 1 << MqttPublishFlags.RETAIN.value()) != 0) + { + retained.doKafkaData(traceId, authorization, budgetId, reserved, flags, payload, kafkaDataEx); + } + else + { + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.fetch(f -> f + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .capabilities(c -> c.set(KafkaCapabilities.PRODUCE_ONLY)) + .key(key))) + .build(); + retained.doKafkaFlush(traceId, authorization, budgetId, reserved, kafkaFlushEx); + } + } + } + + private void addFiltersHeader( + String16FW responseTopic) + { + final DirectBuffer responseBuffer = responseTopic.value(); + final int capacity = responseBuffer.capacity(); + + int offset = 0; + int matchAt = 0; + while (offset >= 0 && offset < capacity && matchAt != -1) + { + matchAt = indexOfByte(responseBuffer, offset, capacity, SLASH_BYTE); + if (matchAt != -1) + { + addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, matchAt - offset); + offset = matchAt + 1; + } + } + addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, capacity - offset); + } + + private void onMqttEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttKafkaState.closeInitial(state); + + assert initialAck <= initialSeq; + + messages.doKafkaEnd(traceId, initialSeq, authorization); + if (retainAvailable) + { + retained.doKafkaEnd(traceId, initialSeq, authorization); + } + } + + private void onMqttAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttKafkaState.closeInitial(state); + + assert initialAck <= initialSeq; + + messages.doKafkaAbort(traceId, authorization); + if (retainAvailable) + { + retained.doKafkaAbort(traceId, authorization); + } + } + + private void onMqttReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final int maximum = reset.maximum(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + messages.doKafkaReset(traceId); + if (retainAvailable) + { + retained.doKafkaReset(traceId); + } + } + + private void onMqttWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyPad = padding; + state = MqttKafkaState.openReply(state); + + assert replyAck <= replySeq; + + messages.doKafkaWindow(traceId, authorization, budgetId, padding, capabilities); + if (retainAvailable) + { + retained.doKafkaWindow(traceId, authorization, budgetId, padding, capabilities); + } + } + + private void doMqttBegin( + long traceId, + long authorization, + long affinity) + { + replySeq = messages.replySeq; + replyAck = messages.replyAck; + replyMax = messages.replyMax; + state = MqttKafkaState.openingReply(state); + + doBegin(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity); + } + + private void doMqttFlush( + long traceId, + long authorization, + long budgetId, + int reserved) + { + replySeq = messages.replySeq; + + doFlush(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization, budgetId, reserved, + EMPTY_OCTETS); + } + + private void doMqttAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.replyClosed(state)) + { + replySeq = messages.replySeq; + state = MqttKafkaState.closeReply(state); + + doAbort(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); + } + } + + private void doMqttEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.replyClosed(state)) + { + replySeq = messages.replySeq; + state = MqttKafkaState.closeReply(state); + + doEnd(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); + } + } + + private void doMqttWindow( + long authorization, + long traceId, + long budgetId, + int padding, + int capabilities) + { + final long newInitialAck = retainAvailable ? Math.min(messages.initialAck, retained.initialAck) : messages.initialAck; + final int newInitialMax = retainAvailable ? Math.min(messages.initialMax, retained.initialMax) : messages.initialMax; + + if (initialAck != newInitialAck || initialMax != newInitialMax) + { + initialAck = newInitialAck; + initialMax = newInitialMax; + + doWindow(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, padding, 0, capabilities); + } + } + + private void doMqttReset( + long traceId) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId); + } + } + } + + private void addHeader( + OctetsFW key, + OctetsFW value) + { + kafkaHeadersRW.item(h -> + { + h.nameLen(key.sizeof()); + h.name(key); + h.valueLen(value.sizeof()); + h.value(value); + }); + } + + private void addHeader( + OctetsFW key, + MqttPayloadFormatFW format) + { + String16FW value = format.get() == MqttPayloadFormat.BINARY ? binaryFormat : textFormat; + addHeader(key, value); + } + + private void addHeader( + OctetsFW key, + String16FW value) + { + DirectBuffer buffer = value.value(); + kafkaHeadersRW.item(h -> + { + h.nameLen(key.sizeof()); + h.name(key); + h.valueLen(value.length()); + h.value(buffer, 0, buffer.capacity()); + }); + } + + private void addHeader( + OctetsFW key, + DirectBuffer buffer, + int offset, + int length) + { + kafkaHeadersRW.item(h -> + { + h.nameLen(key.sizeof()); + h.name(key); + h.valueLen(length); + h.value(buffer, offset, length); + }); + } + + private void addHeader(String16FW key, String16FW value) + { + DirectBuffer keyBuffer = key.value(); + DirectBuffer valueBuffer = value.value(); + kafkaHeadersRW.item(h -> + { + h.nameLen(key.length()); + h.name(keyBuffer, 0, keyBuffer.capacity()); + h.valueLen(value.length()); + h.value(valueBuffer, 0, valueBuffer.capacity()); + }); + } + + private static int indexOfByte( + DirectBuffer buffer, + int offset, + int limit, + byte value) + { + int byteAt = -1; + for (int index = offset; index < limit; index++) + { + if (buffer.getByte(index) == value) + { + byteAt = index; + break; + } + } + return byteAt; + } + + + final class KafkaMessagesProxy + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttPublishProxy delegate; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaMessagesProxy( + long originId, + long routedId, + MqttPublishProxy delegate) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + String16FW kafkaMessagesTopic) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, kafkaMessagesTopic); + } + + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doKafkaEnd( + long traceId, + long sequence, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttBegin(traceId, authorization, affinity); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + doKafkaReset(traceId); + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttEnd(traceId, authorization); + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + delegate.doMqttFlush(traceId, authorization, budgetId, reserved); + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + delegate.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + + delegate.initialAck = acknowledge; + + assert delegate.initialAck <= delegate.initialSeq; + + delegate.doMqttReset(traceId); + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + } + + final class KafkaRetainedProxy + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttPublishProxy delegate; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaRetainedProxy( + long originId, + long routedId, + MqttPublishProxy delegate) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + String16FW kafkaRetainedTopic) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, kafkaRetainedTopic); + } + + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + KafkaFlushExFW extension) + { + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doKafkaEnd( + long traceId, + long sequence, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttBegin(traceId, authorization, affinity); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + doKafkaReset(traceId); + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttEnd(traceId, authorization); + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + delegate.doMqttFlush(traceId, authorization, budgetId, reserved); + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + delegate.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + + delegate.initialAck = acknowledge; + + assert delegate.initialAck <= delegate.initialSeq; + + delegate.doMqttReset(traceId); + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + } + + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + OctetsFW payload, + Flyweight extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private MessageConsumer newKafkaStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW topic) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.capabilities(c -> c.set(KafkaCapabilities.PRODUCE_ONLY)) + .topic(topic) + .partitionsItem(p -> p.partitionId(-1).partitionOffset(-2L)) + .ackMode(b -> b.set(KAFKA_DEFAULT_ACK_MODE))) + .build(); + + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding, + int minimum, + int capabilities) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .minimum(minimum) + .capabilities(capabilities) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } +} diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionFactory.java new file mode 100644 index 0000000000..50492e1efb --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionFactory.java @@ -0,0 +1,3905 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.engine.buffer.BufferPool.NO_SLOT; +import static io.aklivity.zilla.runtime.engine.concurrent.Signaler.NO_CANCEL_ID; +import static java.lang.System.currentTimeMillis; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.agrona.BitUtil.SIZE_OF_INT; +import static org.agrona.BitUtil.SIZE_OF_LONG; + +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.LongFunction; +import java.util.function.LongSupplier; +import java.util.function.LongUnaryOperator; +import java.util.function.Supplier; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.Int2ObjectHashMap; +import org.agrona.collections.IntHashSet; +import org.agrona.collections.Long2ObjectHashMap; +import org.agrona.collections.LongArrayList; +import org.agrona.collections.Object2LongHashMap; +import org.agrona.collections.Object2ObjectHashMap; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.InstanceId; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaHeaderHelper; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaAckMode; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaCapabilities; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaEvaluation; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaHeaderFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaKeyFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaOffsetFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaOffsetType; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttExpirySignalFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormatFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPublishFlags; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSessionFlags; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSessionSignalFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSessionStateFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttTime; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttWillMessageFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttWillSignalFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaGroupBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaGroupFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttResetExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttServerCapabilities; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSessionBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSessionDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.SignalFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.Configuration.IntPropertyDef; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; +import io.aklivity.zilla.runtime.engine.concurrent.Signaler; + +public class MqttKafkaSessionFactory implements MqttKafkaStreamFactory +{ + private static final byte SLASH_BYTE = (byte) '/'; + private static final KafkaAckMode KAFKA_DEFAULT_ACK_MODE = KafkaAckMode.LEADER_ONLY; + private static final String KAFKA_TYPE_NAME = "kafka"; + private static final String MQTT_TYPE_NAME = "mqtt"; + private static final String MIGRATE_KEY_POSTFIX = "#migrate"; + private static final String WILL_SIGNAL_KEY_POSTFIX = "#will-signal"; + private static final String EXPIRY_SIGNAL_KEY_POSTFIX = "#expiry-signal"; + private static final String WILL_KEY_POSTFIX = "#will-"; + private static final String GROUP_PROTOCOL = "highlander"; + private static final String16FW SENDER_ID_NAME = new String16FW("sender-id"); + private static final String16FW TYPE_HEADER_NAME = new String16FW("type"); + private static final OctetsFW TYPE_HEADER_NAME_OCTETS = + new OctetsFW().wrap(TYPE_HEADER_NAME.value(), 0, TYPE_HEADER_NAME.length()); + private static final String16FW WILL_SIGNAL_NAME = new String16FW("will-signal"); + private static final OctetsFW WILL_SIGNAL_NAME_OCTETS = + new OctetsFW().wrap(WILL_SIGNAL_NAME.value(), 0, WILL_SIGNAL_NAME.length()); + private static final String16FW EXPIRY_SIGNAL_NAME = new String16FW("expiry-signal"); + private static final OctetsFW EXPIRY_SIGNAL_NAME_OCTETS = + new OctetsFW().wrap(EXPIRY_SIGNAL_NAME.value(), 0, EXPIRY_SIGNAL_NAME.length()); + private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(new UnsafeBuffer(new byte[0]), 0, 0); + private static final int DATA_FLAG_INIT = 0x02; + private static final int DATA_FLAG_FIN = 0x01; + private static final int DATA_FLAG_COMPLETE = 0x03; + public static final String MQTT_CLIENTS_GROUP_ID = "mqtt-clients"; + private static final int SIGNAL_DELIVER_WILL_MESSAGE = 1; + private static final int SIGNAL_CONNECT_WILL_STREAM = 2; + private static final int SIGNAL_EXPIRE_SESSION = 3; + private static final int SIZE_OF_UUID = 38; + private static final AtomicInteger CONTEXT_COUNTER = new AtomicInteger(0); + private static final int RETAIN_AVAILABLE_MASK = 1 << MqttServerCapabilities.RETAIN.value(); + private static final int WILDCARD_AVAILABLE_MASK = 1 << MqttServerCapabilities.WILDCARD.value(); + private static final int SUBSCRIPTION_IDS_AVAILABLE_MASK = 1 << MqttServerCapabilities.SUBSCRIPTION_IDS.value(); + private static final int SHARED_SUBSCRIPTIONS_AVAILABLE_MASK = 1 << MqttServerCapabilities.SHARED_SUBSCRIPTIONS.value(); + private static final byte MQTT_KAFKA_MAX_QOS = 0; + private static final int MQTT_KAFKA_CAPABILITIES = RETAIN_AVAILABLE_MASK | WILDCARD_AVAILABLE_MASK | + SUBSCRIPTION_IDS_AVAILABLE_MASK; + + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final AbortFW abortRO = new AbortFW(); + private final FlushFW flushRO = new FlushFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + private final MqttWillMessageFW.Builder mqttMessageRW = new MqttWillMessageFW.Builder(); + private final MqttSessionSignalFW.Builder mqttSessionSignalRW = new MqttSessionSignalFW.Builder(); + private final Array32FW.Builder kafkaHeadersRW = + new Array32FW.Builder<>(new KafkaHeaderFW.Builder(), new KafkaHeaderFW()); + + private final WindowFW windowRO = new WindowFW(); + private final ResetFW resetRO = new ResetFW(); + private final SignalFW signalRO = new SignalFW(); + + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + + private final ExtensionFW extensionRO = new ExtensionFW(); + private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); + private final MqttSessionStateFW mqttSessionStateRO = new MqttSessionStateFW(); + private final MqttSessionSignalFW mqttSessionSignalRO = new MqttSessionSignalFW(); + private final MqttWillMessageFW mqttWillRO = new MqttWillMessageFW(); + private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); + private final MqttResetExFW.Builder mqttResetExRW = new MqttResetExFW.Builder(); + private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); + private final KafkaDataExFW kafkaDataExRO = new KafkaDataExFW(); + private final KafkaResetExFW kafkaResetExRO = new KafkaResetExFW(); + private final KafkaFlushExFW kafkaFlushExRO = new KafkaFlushExFW(); + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); + private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); + private final MqttBeginExFW.Builder mqttSessionBeginExRW = new MqttBeginExFW.Builder(); + private final String16FW binaryFormat = new String16FW(MqttPayloadFormat.BINARY.name()); + private final String16FW textFormat = new String16FW(MqttPayloadFormat.TEXT.name()); + + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final MutableDirectBuffer kafkaHeadersBuffer; + private final MutableDirectBuffer willMessageBuffer; + private final MutableDirectBuffer sessionSignalBuffer; + private final MutableDirectBuffer willKeyBuffer; + private final MutableDirectBuffer sessionSignalKeyBuffer; + private final MutableDirectBuffer sessionExtBuffer; + private final int packetSizeMax; + private final BufferPool bufferPool; + private final BindingHandler streamFactory; + private final Signaler signaler; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final int kafkaTypeId; + private final int mqttTypeId; + private final LongFunction supplyBinding; + private final Supplier supplySessionId; + private final Supplier supplyWillId; + private final Supplier supplyLifetimeId; + private final LongSupplier supplyTime; + private final Long2ObjectHashMap sessionIds; + private final MqttKafkaHeaderHelper helper; + private final int coreIndex; + private final Supplier supplyTraceId; + private final Object2ObjectHashMap willDeliverIds; + private final Object2LongHashMap sessionExpiryIds; + private final InstanceId instanceId; + private final boolean willAvailable; + private final int reconnectDelay; + + private String serverRef; + private int reconnectAttempt; + + public MqttKafkaSessionFactory( + MqttKafkaConfiguration config, + EngineContext context, + InstanceId instanceId, + LongFunction supplyBinding, + IntPropertyDef reconnectDelay) + { + this.kafkaTypeId = context.supplyTypeId(KAFKA_TYPE_NAME); + this.mqttTypeId = context.supplyTypeId(MQTT_TYPE_NAME); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.kafkaHeadersBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.willMessageBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.sessionSignalBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.willKeyBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.sessionSignalKeyBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.sessionExtBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.packetSizeMax = writeBuffer.capacity(); + this.bufferPool = context.bufferPool(); + this.helper = new MqttKafkaHeaderHelper(); + this.streamFactory = context.streamFactory(); + this.signaler = context.signaler(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyBinding = supplyBinding; + this.supplySessionId = config.sessionId(); + this.supplyWillId = config.willId(); + this.supplyLifetimeId = config.lifetimeId(); + this.supplyTime = config.time(); + this.supplyTraceId = context::supplyTraceId; + this.sessionIds = new Long2ObjectHashMap<>(); + this.coreIndex = context.index(); + this.willAvailable = config.willAvailable(); + this.willDeliverIds = new Object2ObjectHashMap<>(); + this.sessionExpiryIds = new Object2LongHashMap<>(-1); + this.instanceId = instanceId; + this.reconnectDelay = reconnectDelay.getAsInt(config); + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer mqtt) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + + final MqttKafkaBindingConfig binding = supplyBinding.apply(routedId); + + final MqttKafkaRouteConfig resolved = binding != null ? binding.resolve(authorization) : null; + + MessageConsumer newStream = null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + final String16FW sessionTopic = binding.sessionsTopic(); + newStream = new MqttSessionProxy(mqtt, originId, routedId, initialId, resolvedId, + binding.id, sessionTopic)::onMqttMessage; + } + + return newStream; + } + + @Override + public void onAttached( + long bindingId) + { + MqttKafkaBindingConfig binding = supplyBinding.apply(bindingId); + this.serverRef = binding.options.serverRef; + if (willAvailable && coreIndex == 0) + { + Optional route = binding.routes.stream().findFirst(); + final long routeId = route.map(mqttKafkaRouteConfig -> mqttKafkaRouteConfig.id).orElse(0L); + + binding.willProxy = new KafkaSignalStream(binding.id, routeId, + binding.sessionsTopic(), binding.messagesTopic(), binding.retainedTopic()); + binding.willProxy.doKafkaBegin(currentTimeMillis()); + } + sessionIds.put(bindingId, supplySessionId.get()); + } + + @Override + public void onDetached( + long bindingId) + { + MqttKafkaBindingConfig binding = supplyBinding.apply(bindingId); + sessionIds.remove(bindingId); + + if (binding.willProxy != null) + { + binding.willProxy.doKafkaEnd(supplyTraceId.get(), 0); + binding.willProxy = null; + } + } + + private final class MqttSessionProxy + { + private final MessageConsumer mqtt; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final String16FW sessionId; + private final String16FW sessionsTopic; + private String lifetimeId; + private KafkaSessionStream session; + private KafkaGroupStream group; + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private String16FW clientId; + private String16FW clientIdMigrate; + private int sessionExpiryMillis; + private int sessionFlags; + private int sessionPadding; + private String willId; + private int delay; + + private MqttSessionProxy( + MessageConsumer mqtt, + long originId, + long routedId, + long initialId, + long resolvedId, + long bindingId, + String16FW sessionsTopic) + { + this.mqtt = mqtt; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.session = new KafkaFetchWillSignalStream(originId, resolvedId, this); + this.sessionsTopic = sessionsTopic; + this.sessionId = new String16FW(sessionIds.get(bindingId)); + } + + private void onMqttMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onMqttBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onMqttData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onMqttEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onMqttAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onMqttReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onMqttWindow(window); + break; + } + } + + private void onMqttBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + state = MqttKafkaState.openingInitial(state); + + assert initialAck <= initialSeq; + + final OctetsFW extension = begin.extension(); + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + + assert mqttBeginEx.kind() == MqttBeginExFW.KIND_SESSION; + final MqttSessionBeginExFW mqttSessionBeginEx = mqttBeginEx.session(); + + final String clientId0 = mqttSessionBeginEx.clientId().asString(); + this.clientId = new String16FW(clientId0); + this.clientIdMigrate = new String16FW(clientId0 + MIGRATE_KEY_POSTFIX); + + sessionExpiryMillis = (int) SECONDS.toMillis(mqttSessionBeginEx.expiry()); + sessionFlags = mqttSessionBeginEx.flags(); + + if (!isSetWillFlag(sessionFlags) || isSetCleanStart(sessionFlags)) + { + final long routedId = session.routedId; + session = new KafkaSessionSignalStream(originId, routedId, this); + } + if (isSetWillFlag(sessionFlags)) + { + final int willSignalSize = 1 + clientId.sizeof() + SIZE_OF_INT + SIZE_OF_LONG + SIZE_OF_UUID + SIZE_OF_UUID + + instanceId.instanceId().sizeof(); + sessionPadding = willSignalSize + SIZE_OF_UUID + SIZE_OF_UUID; + } + final int expirySignalSize = 1 + clientId.sizeof() + SIZE_OF_INT + SIZE_OF_LONG + instanceId.instanceId().sizeof(); + sessionPadding += expirySignalSize; + + session.doKafkaBeginIfNecessary(traceId, authorization, affinity); + } + + private void onMqttData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int flags = data.flags(); + final int reserved = data.reserved(); + final OctetsFW extension = data.extension(); + final OctetsFW payload = data.payload(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + + + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final MqttDataExFW mqttDataEx = + dataEx != null && dataEx.typeId() == mqttTypeId ? extension.get(mqttDataExRO::tryWrap) : null; + final MqttSessionDataExFW mqttSessionDataEx = + mqttDataEx != null && mqttDataEx.kind() == MqttDataExFW.KIND_SESSION ? mqttDataEx.session() : null; + + Flyweight kafkaDataEx; + Flyweight kafkaPayload; + if (mqttSessionDataEx != null) + { + switch (mqttSessionDataEx.kind().get()) + { + case WILL: + if (lifetimeId == null) + { + lifetimeId = supplyLifetimeId.get(); + } + this.willId = supplyWillId.get(); + + String16FW key = new String16FW.Builder().wrap(willKeyBuffer, 0, willKeyBuffer.capacity()) + .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, StandardCharsets.UTF_8).build(); + kafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(key.length()) + .value(key.value(), 0, key.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length()))) + .build(); + + MqttWillMessageFW will = mqttWillRO.tryWrap(buffer, offset, limit); + this.delay = (int) Math.min(SECONDS.toMillis(will.delay()), sessionExpiryMillis); + final int expiryInterval = will.expiryInterval() == -1 ? -1 : + (int) TimeUnit.SECONDS.toMillis(will.expiryInterval()); + final MqttWillMessageFW.Builder willMessageBuilder = + mqttMessageRW.wrap(willMessageBuffer, 0, willMessageBuffer.capacity()) + .topic(will.topic()) + .delay(delay) + .qos(will.qos()) + .flags(will.flags()) + .expiryInterval(expiryInterval) + .contentType(will.contentType()) + .format(will.format()) + .responseTopic(will.responseTopic()) + .lifetimeId(lifetimeId) + .willId(willId) + .correlation(will.correlation()) + .properties(will.properties()) + .payload(will.payload()); + + kafkaPayload = willMessageBuilder.build(); + session.doKafkaData(traceId, authorization, budgetId, + kafkaPayload.sizeof(), flags, kafkaPayload, kafkaDataEx); + + + String16FW willSignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + Flyweight willSignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(willSignalKey.length()) + .value(willSignalKey.value(), 0, willSignalKey.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) + .value(WILL_SIGNAL_NAME_OCTETS))) + .build(); + + final MqttSessionSignalFW willSignal = + mqttSessionSignalRW.wrap(sessionSignalBuffer, 0, sessionSignalBuffer.capacity()) + .will(w -> w + .instanceId(instanceId.instanceId()) + .clientId(clientId) + .delay(delay) + .deliverAt(MqttTime.UNKNOWN.value()) + .lifetimeId(lifetimeId) + .willId(willId)) + .build(); + + session.doKafkaData(traceId, authorization, budgetId, willSignal.sizeof(), flags, + willSignal, willSignalKafkaDataEx); + + + doFlushProduceAndFetchWithFilter(traceId, authorization, budgetId); + break; + case STATE: + kafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length()))) + .build(); + + kafkaPayload = payload.sizeof() > 0 ? mqttSessionStateRO.wrap(buffer, offset, limit) : EMPTY_OCTETS; + + session.doKafkaData(traceId, authorization, budgetId, + reserved, flags, kafkaPayload, kafkaDataEx); + break; + } + } + } + + private void doFlushProduceAndFetchWithFilter( + long traceId, + long authorization, + long budgetId) + { + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.fetch(f -> + { + f.capabilities(c -> c.set(KafkaCapabilities.PRODUCE_AND_FETCH)); + f.filtersItem(fi -> fi.conditionsItem(ci -> + ci.key(kb -> kb.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())))); + f.filtersItem(fi -> + { + fi.conditionsItem(ci -> + ci.key(kb -> kb.length(clientIdMigrate.length()) + .value(clientIdMigrate.value(), 0, clientIdMigrate.length()))); + fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(SENDER_ID_NAME.length()) + .name(SENDER_ID_NAME.value(), 0, SENDER_ID_NAME.length()) + .valueLen(sessionId.length()) + .value(sessionId.value(), 0, sessionId.length()))))); + }); + })) + .build(); + + session.doKafkaFlush(traceId, authorization, budgetId, 0, kafkaFlushEx); + } + + private void onMqttEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttKafkaState.closeInitial(state); + + assert initialAck <= initialSeq; + + if (isSetWillFlag(sessionFlags)) + { + // Cleanup will message + will signal + String16FW key = new String16FW.Builder().wrap(willKeyBuffer, 0, willKeyBuffer.capacity()) + .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, StandardCharsets.UTF_8).build(); + Flyweight kafkaWillDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(key.length()) + .value(key.value(), 0, key.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length()))) + .build(); + + session.doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, + null, kafkaWillDataEx); + + String16FW willSignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + Flyweight willSignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(willSignalKey.length()) + .value(willSignalKey.value(), 0, willSignalKey.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) + .value(WILL_SIGNAL_NAME_OCTETS))) + .build(); + + session.doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, + null, willSignalKafkaDataEx); + } + + final MqttSessionSignalFW expirySignal = + mqttSessionSignalRW.wrap(sessionSignalBuffer, 0, sessionSignalBuffer.capacity()) + .expiry(w -> w + .instanceId(instanceId.instanceId()) + .clientId(clientId) + .delay(sessionExpiryMillis) + .expireAt(supplyTime.getAsLong() + sessionExpiryMillis)) + .build(); + session.sendExpirySignal(authorization, traceId, expirySignal); // expire at expireAt + + session.doKafkaEnd(traceId, authorization); + if (group != null) + { + group.doKafkaEnd(traceId, authorization); + } + } + + private void onMqttAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttKafkaState.closeInitial(state); + + assert initialAck <= initialSeq; + + if (isSetWillFlag(sessionFlags)) + { + session.sendWillSignal(traceId, authorization); + } + final MqttSessionSignalFW expirySignal = + mqttSessionSignalRW.wrap(sessionSignalBuffer, 0, sessionSignalBuffer.capacity()) + .expiry(w -> w + .instanceId(instanceId.instanceId()) + .clientId(clientId) + .delay(sessionExpiryMillis) + .expireAt(supplyTime.getAsLong() + sessionExpiryMillis)) + .build(); + session.sendExpirySignal(authorization, traceId, expirySignal); // expire at expireAt + + session.doKafkaAbort(traceId, authorization); + if (group != null) + { + group.doKafkaAbort(traceId, authorization); + } + } + + private void onMqttReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final int maximum = reset.maximum(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + session.doKafkaReset(traceId); + if (group != null) + { + group.doKafkaReset(traceId); + } + } + + private void onMqttWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + final boolean wasOpen = MqttKafkaState.replyOpened(state); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyPad = padding; + state = MqttKafkaState.openReply(state); + + assert replyAck <= replySeq; + + session.doKafkaWindow(traceId, authorization, budgetId, capabilities); + if (!wasOpen && group != null) + { + group.doKafkaWindow(traceId, authorization, budgetId, padding, capabilities); + } + } + + private void doMqttBegin( + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + if (!MqttKafkaState.replyOpening(state)) + { + replySeq = session.replySeq; + replyAck = session.replyAck; + replyMax = session.replyMax; + state = MqttKafkaState.openingReply(state); + + doBegin(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, extension); + } + } + + private void doMqttData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + MqttSessionStateFW sessionState) + { + Flyweight state = sessionState == null ? EMPTY_OCTETS : sessionState; + final DirectBuffer buffer = state.buffer(); + final int offset = state.offset(); + final int limit = state.limit(); + final int length = limit - offset; + + doData(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, flags, reserved, buffer, offset, length, EMPTY_OCTETS); + + replySeq += reserved; + + assert replySeq <= replyAck + replyMax; + } + + private void doMqttData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload) + { + doData(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, flags, reserved, payload, EMPTY_OCTETS); + + replySeq += reserved; + + assert replySeq <= replyAck + replyMax; + } + + private void doMqttAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.replyClosed(state)) + { + replySeq = session.replySeq; + state = MqttKafkaState.closeReply(state); + + doAbort(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); + } + } + + private void doMqttEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.replyClosed(state)) + { + replySeq = session.replySeq; + state = MqttKafkaState.closeReply(state); + + doEnd(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); + } + } + + private void doMqttWindow( + long authorization, + long traceId, + long budgetId, + int padding, + int capabilities) + { + initialAck = session.initialAck - padding; + initialMax = session.initialMax; + + doWindow(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, padding, 0, capabilities); + } + + private void doMqttReset( + long traceId, + Flyweight extension) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, extension); + } + } + } + + public final class KafkaSignalStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final String16FW sessionsTopic; + private final String16FW messagesTopic; + private final String16FW retainedTopic; + private final Object2ObjectHashMap willFetchers; + private final Int2ObjectHashMap expiryClientIds; + + private IntHashSet partitions; + private int state; + + private long replySeq; + private long replyAck; + private int replyMax; + private long reconnectAt; + private int decodeSlot = NO_SLOT; + private int decodeSlotOffset; + + private KafkaSignalStream( + long originId, + long routedId, + String16FW sessionsTopic, + String16FW messagesTopic, + String16FW retainedTopic) + { + this.originId = originId; + this.routedId = routedId; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.sessionsTopic = sessionsTopic; + this.messagesTopic = messagesTopic; + this.retainedTopic = retainedTopic; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.willFetchers = new Object2ObjectHashMap<>(); + this.expiryClientIds = new Int2ObjectHashMap<>(); + this.partitions = new IntHashSet(); + + } + + private void doKafkaBegin( + long timeMillis) + { + this.reconnectAt = signaler.signalAt( + timeMillis, + SIGNAL_CONNECT_WILL_STREAM, + this::onSignalConnectWillStream); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + reconnectAttempt = 0; + willFetchers.values().forEach(f -> f.cleanup(traceId, authorization)); + willFetchers.clear(); + + state = MqttKafkaState.openingInitial(state); + + kafka = newSignalStream(this::onSignalMessage, originId, routedId, initialId, 0, 0, 0, + traceId, authorization, affinity, sessionsTopic); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + + signaler.cancel(reconnectAt); + reconnectAt = NO_CANCEL_ID; + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + } + } + + private void onSignalMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onSignal(signal); + break; + } + } + + private void onSignal(SignalFW signal) + { + final int signalId = signal.signalId(); + + switch (signalId) + { + case SIGNAL_EXPIRE_SESSION: + onKafkaSessionExpirySignal(signal); + break; + default: + break; + } + } + + private void onKafkaSessionExpirySignal( + SignalFW signal) + { + String16FW clientId = expiryClientIds.get(signal.contextId()); + + Flyweight expireSessionKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length()))) + .build(); + + doKafkaData(supplyTraceId.get(), 0, expireSessionKafkaDataEx); + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + doKafkaWindow(traceId, authorization, 0, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + } + else + { + final OctetsFW extension = data.extension(); + final OctetsFW payload = data.payload(); + final int flags = data.flags(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key() : null; + + reactToSignal: + { + if (key != null && payload == null && (flags & DATA_FLAG_FIN) != 0x00) + { + final OctetsFW type = kafkaMergedDataEx.headers() + .matchFirst(h -> h.name().equals(TYPE_HEADER_NAME_OCTETS)).value(); + + final String keyPostfix = type.equals(WILL_SIGNAL_NAME_OCTETS) ? + WILL_SIGNAL_KEY_POSTFIX : EXPIRY_SIGNAL_KEY_POSTFIX; + + final String clientId0 = key.value() + .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o - keyPostfix.length())); + final String16FW clientId = new String16FW(clientId0); + + if (type.equals(WILL_SIGNAL_NAME_OCTETS) && willDeliverIds.containsKey(clientId)) + { + willDeliverIds.get(clientId).forEach(signaler::cancel); + KafkaFetchWillStream willFetcher = willFetchers.get(clientId); + if (willFetcher != null) + { + willFetcher.cleanup(traceId, authorization); + } + } + else if (type.equals(EXPIRY_SIGNAL_NAME_OCTETS) && sessionExpiryIds.containsKey(clientId)) + { + signaler.cancel(sessionExpiryIds.get(clientId)); + } + + break reactToSignal; + } + + DirectBuffer buffer = payload.buffer(); + int offset = payload.offset(); + int limit = payload.limit(); + int length = limit - offset; + + if ((flags & DATA_FLAG_FIN) == 0x00) + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = bufferPool.acquire(replyId); + assert decodeSlotOffset == 0; + } + + final MutableDirectBuffer slotBuffer = bufferPool.buffer(decodeSlot); + slotBuffer.putBytes(decodeSlotOffset, buffer, offset, length); + decodeSlotOffset += length; + } + else + { + if (decodeSlot != NO_SLOT) + { + final MutableDirectBuffer slotBuffer = bufferPool.buffer(decodeSlot); + slotBuffer.putBytes(decodeSlotOffset, buffer, offset, length); + buffer = slotBuffer; + offset = 0; + limit = decodeSlotOffset + length; + } + + final MqttSessionSignalFW sessionSignal = + mqttSessionSignalRO.wrap(buffer, offset, limit); + byte[] bytes = new byte[sessionSignal.sizeof()]; + + switch (sessionSignal.kind()) + { + case MqttSessionSignalFW.KIND_WILL: + final MqttWillSignalFW willSignal = sessionSignal.will(); + long deliverAt = willSignal.deliverAt(); + final String16FW willClientId = willSignal.clientId(); + + if (deliverAt == MqttTime.UNKNOWN.value()) + { + if (instanceId.instanceId().equals(willSignal.instanceId())) + { + break reactToSignal; + } + deliverAt = supplyTime.getAsLong() + willSignal.delay(); + } + + KafkaFetchWillStream willFetcher = + new KafkaFetchWillStream(originId, routedId, this, sessionsTopic, willClientId, + willSignal.willId().asString(), willSignal.lifetimeId().asString(), deliverAt); + willFetcher.doKafkaBegin(traceId, authorization, 0, willSignal.lifetimeId()); + willFetchers.put(new String16FW(willClientId.asString()), willFetcher); + break; + case MqttSessionSignalFW.KIND_EXPIRY: + final MqttExpirySignalFW expirySignal = sessionSignal.expiry(); + long expireAt = expirySignal.expireAt(); + final String16FW expiryClientId = expirySignal.clientId(); + + if (expireAt == MqttTime.UNKNOWN.value()) + { + if (instanceId.instanceId().equals(expirySignal.instanceId())) + { + break reactToSignal; + } + expireAt = supplyTime.getAsLong() + expirySignal.delay(); + } + + final int contextId = CONTEXT_COUNTER.incrementAndGet(); + expiryClientIds.put(contextId, expiryClientId); + + final long signalId = + signaler.signalAt(expireAt, originId, routedId, initialId, SIGNAL_EXPIRE_SESSION, contextId); + sessionExpiryIds.put(expiryClientId, signalId); + break; + } + + if (decodeSlot != NO_SLOT) + { + bufferPool.release(decodeSlot); + decodeSlot = NO_SLOT; + decodeSlotOffset = 0; + } + } + } + } + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + final OctetsFW extension = flush.extension(); + final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); + final KafkaFlushExFW kafkaFlushEx = + flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; + final KafkaMergedFlushExFW kafkaMergedFlushEx = + kafkaFlushEx != null && kafkaFlushEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaFlushEx.merged() : null; + final Array32FW progress = kafkaMergedFlushEx != null ? kafkaMergedFlushEx.fetch().progress() : null; + + if (progress != null) + { + final IntHashSet newPartitions = new IntHashSet(); + progress.forEach(p -> newPartitions.add(p.partitionId())); + if (!newPartitions.equals(partitions)) + { + instanceId.regenerate(); + partitions = newPartitions; + } + } + } + + private void onSignalConnectWillStream( + int signalId) + { + assert signalId == SIGNAL_CONNECT_WILL_STREAM; + + this.reconnectAt = NO_CANCEL_ID; + doKafkaBegin(supplyTraceId.get(), 0, 0); + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + doKafkaEnd(traceId, authorization); + + if (reconnectDelay != 0) + { + if (reconnectAt != NO_CANCEL_ID) + { + signaler.cancel(reconnectAt); + } + + reconnectAt = signaler.signalAt( + currentTimeMillis() + SECONDS.toMillis(reconnectDelay), + SIGNAL_CONNECT_WILL_STREAM, + this::onSignalConnectWillStream); + } + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + doKafkaAbort(traceId, authorization); + + if (reconnectDelay != 0) + { + if (reconnectAt != NO_CANCEL_ID) + { + signaler.cancel(reconnectAt); + } + + reconnectAt = signaler.signalAt( + currentTimeMillis() + SECONDS.toMillis(reconnectDelay), + SIGNAL_CONNECT_WILL_STREAM, + this::onSignalConnectWillStream); + } + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + + assert acknowledge <= sequence; + + if (reconnectDelay != 0) + { + if (reconnectAt != NO_CANCEL_ID) + { + signaler.cancel(reconnectAt); + } + + reconnectAt = signaler.signalAt( + currentTimeMillis() + Math.min(50 << reconnectAttempt++, SECONDS.toMillis(reconnectDelay)), + SIGNAL_CONNECT_WILL_STREAM, + this::onSignalConnectWillStream); + } + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyMax = 8192; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, 0, capabilities); + } + + + private void doKafkaData( + long traceId, + long authorization, + Flyweight extension) + { + + doData(kafka, originId, routedId, initialId, 0, 0, 0, + traceId, authorization, 0, DATA_FLAG_COMPLETE, 0, null, extension); + } + } + + private final class KafkaFetchWillStream + { + private final KafkaSignalStream delegate; + private final String16FW topic; + private final String16FW clientId; + private final String lifetimeId; + private final String willId; + private final long deliverAt; + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private int dataSlot = NO_SLOT; + private int messageSlotOffset; + private int messageSlotReserved; + private KafkaProduceWillStream willProducer; + private KafkaProduceWillStream willRetainProducer; + private int willMessageAckCount; + + private KafkaFetchWillStream( + long originId, + long routedId, + KafkaSignalStream delegate, + String16FW topic, + String16FW clientId, + String willId, + String lifetimeId, + long deliverAt) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.topic = topic; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.clientId = clientId; + this.willId = willId; + this.lifetimeId = lifetimeId; + this.deliverAt = deliverAt; + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + String16FW lifetimeId) + { + if (!MqttKafkaState.initialOpening(state)) + { + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, clientId, lifetimeId, topic); + } + } + + private void cleanup( + long traceId, + long authorization) + { + doKafkaEnd(traceId, authorization); + if (willProducer != null) + { + willProducer.doKafkaEnd(traceId, authorization); + } + if (willRetainProducer != null) + { + willRetainProducer.doKafkaEnd(traceId, authorization); + } + bufferPool.release(dataSlot); + dataSlot = NO_SLOT; + messageSlotOffset = 0; + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + delegate.willFetchers.remove(clientId); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + doKafkaWindow(traceId, authorization, 0, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + } + else + { + final OctetsFW extension = data.extension(); + final OctetsFW payload = data.payload(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key() : null; + + if (key != null && payload != null) + { + MqttWillMessageFW willMessage = + mqttWillRO.wrap(payload.buffer(), payload.offset(), payload.limit()); + + if (willId.equals(willMessage.willId().asString())) + { + if (dataSlot == NO_SLOT) + { + dataSlot = bufferPool.acquire(initialId); + } + + if (dataSlot == NO_SLOT) + { + doKafkaAbort(traceId, authorization); + } + + + final MutableDirectBuffer dataBuffer = bufferPool.buffer(dataSlot); + dataBuffer.putBytes(0, willMessage.buffer(), willMessage.offset(), willMessage.sizeof()); + + messageSlotReserved = willMessage.sizeof(); + + willProducer = + new KafkaProduceWillStream(originId, routedId, this, delegate.messagesTopic, deliverAt); + willProducer.doKafkaBegin(traceId, authorization, 0); + willMessageAckCount++; + if ((willMessage.flags() & 1 << MqttPublishFlags.RETAIN.value()) != 0) + { + willRetainProducer = + new KafkaProduceWillStream(originId, routedId, this, delegate.retainedTopic, deliverAt); + willRetainProducer.doKafkaBegin(traceId, authorization, 0); + willMessageAckCount++; + } + } + else + { + doKafkaEnd(traceId, authorization); + } + } + } + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + doKafkaEnd(traceId, authorization); + } + + private void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + + assert acknowledge <= sequence; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + } + + private void doKafkaReset( + long traceId) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyMax = bufferPool.slotCapacity(); + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + + private void onWillMessageAcked( + long traceId, + long authorization) + { + if (--willMessageAckCount == 0) + { + bufferPool.release(dataSlot); + dataSlot = NO_SLOT; + messageSlotOffset = 0; + + // Cleanup will message + will signal + String16FW key = new String16FW.Builder().wrap(willKeyBuffer, 0, willKeyBuffer.capacity()) + .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, StandardCharsets.UTF_8).build(); + Flyweight kafkaWillDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(key.length()) + .value(key.value(), 0, key.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length()))) + .build(); + + delegate.doKafkaData(traceId, authorization, kafkaWillDataEx); + + String16FW willSignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + Flyweight willSignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(willSignalKey.length()) + .value(willSignalKey.value(), 0, willSignalKey.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) + .value(WILL_SIGNAL_NAME_OCTETS))) + .build(); + + delegate.doKafkaData(traceId, authorization, willSignalKafkaDataEx); + + doKafkaEnd(traceId, authorization); + } + } + } + + private final class KafkaProduceWillStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final String16FW kafkaTopic; + private final long deliverAt; + private final long replyId; + private final KafkaFetchWillStream delegate; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaProduceWillStream( + long originId, + long routedId, + KafkaFetchWillStream delegate, + String16FW kafkaTopic, + long deliverAt) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.kafkaTopic = kafkaTopic; + this.deliverAt = deliverAt; + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, kafkaTopic); + } + + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onKafkaSignal(signal); + break; + } + } + + private void onKafkaSignal( + SignalFW signal) + { + final int signalId = signal.signalId(); + + switch (signalId) + { + case SIGNAL_DELIVER_WILL_MESSAGE: + onWillDeliverSignal(signal); + break; + default: + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + doKafkaWindow(traceId, authorization, 0, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + doKafkaReset(traceId); + } + + private void onKafkaWindow( + WindowFW window) + { + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + if (!wasOpen) + { + final long signalId = + signaler.signalAt(deliverAt, originId, routedId, initialId, SIGNAL_DELIVER_WILL_MESSAGE, 0); + willDeliverIds.computeIfAbsent(delegate.clientId, k -> new LongArrayList()).add(signalId); + } + if (initialAck == delegate.messageSlotReserved) + { + doKafkaEnd(traceId, authorization); + delegate.onWillMessageAcked(traceId, authorization); + } + } + + + private void onWillDeliverSignal(SignalFW signal) + { + sendWill(signal.traceId(), signal.authorization(), 0); + willDeliverIds.remove(delegate.clientId); + } + + private void sendWill( + long traceId, + long authorization, + long budgetId) + { + final MutableDirectBuffer dataBuffer = bufferPool.buffer(delegate.dataSlot); + // TODO: data fragmentation + final MqttWillMessageFW will = mqttWillRO.wrap(dataBuffer, delegate.messageSlotOffset, dataBuffer.capacity()); + + Flyweight kafkaDataEx; + + kafkaHeadersRW.wrap(kafkaHeadersBuffer, 0, kafkaHeadersBuffer.capacity()); + + + String topicName = will.topic().asString(); + assert topicName != null; + + final DirectBuffer topicNameBuffer = will.topic().value(); + + final MutableDirectBuffer keyBuffer = new UnsafeBuffer(new byte[topicNameBuffer.capacity() + 4]); + final KafkaKeyFW key = new KafkaKeyFW.Builder() + .wrap(keyBuffer, 0, keyBuffer.capacity()) + .length(topicNameBuffer.capacity()) + .value(topicNameBuffer, 0, topicNameBuffer.capacity()) + .build(); + + String[] topicHeaders = topicName.split("/"); + for (String header : topicHeaders) + { + String16FW topicHeader = new String16FW(header); + addHeader(helper.kafkaFilterHeaderName, topicHeader); + } + + if (will.expiryInterval() != -1) + { + final MutableDirectBuffer expiryBuffer = new UnsafeBuffer(new byte[4]); + expiryBuffer.putInt(0, will.expiryInterval(), ByteOrder.BIG_ENDIAN); + kafkaHeadersRW.item(h -> + { + h.nameLen(helper.kafkaTimeoutHeaderName.sizeof()); + h.name(helper.kafkaTimeoutHeaderName); + h.valueLen(4); + h.value(expiryBuffer, 0, expiryBuffer.capacity()); + }); + } + + if (will.contentType().length() != -1) + { + addHeader(helper.kafkaContentTypeHeaderName, will.contentType()); + } + + if (will.payload().sizeof() != 0 && will.format() != null) + { + addHeader(helper.kafkaFormatHeaderName, will.format()); + } + + if (will.responseTopic().length() != -1) + { + final String16FW responseTopic = will.responseTopic(); + addHeader(helper.kafkaReplyToHeaderName, kafkaTopic); + addHeader(helper.kafkaReplyKeyHeaderName, responseTopic); + + addFiltersHeader(responseTopic); + } + + if (will.correlation().bytes() != null) + { + addHeader(helper.kafkaCorrelationHeaderName, will.correlation().bytes()); + } + + will.properties().forEach(property -> + addHeader(property.key(), property.value())); + + kafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.set(key)) + .headers(kafkaHeadersRW.build())) + .build(); + + doKafkaData(traceId, authorization, budgetId, will.sizeof(), DATA_FLAG_COMPLETE, will.payload().bytes(), kafkaDataEx); + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void addHeader( + OctetsFW key, + OctetsFW value) + { + kafkaHeadersRW.item(h -> + { + h.nameLen(key.sizeof()); + h.name(key); + h.valueLen(value.sizeof()); + h.value(value); + }); + } + + private void addFiltersHeader( + String16FW responseTopic) + { + final DirectBuffer responseBuffer = responseTopic.value(); + final int capacity = responseBuffer.capacity(); + + int offset = 0; + int matchAt = 0; + while (offset >= 0 && offset < capacity && matchAt != -1) + { + matchAt = indexOfByte(responseBuffer, offset, capacity, SLASH_BYTE); + if (matchAt != -1) + { + addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, matchAt - offset); + offset = matchAt + 1; + } + } + addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, capacity - offset); + } + + private void addHeader( + OctetsFW key, + MqttPayloadFormatFW format) + { + String16FW value = format.get() == MqttPayloadFormat.BINARY ? binaryFormat : textFormat; + addHeader(key, value); + } + + private void addHeader( + OctetsFW key, + String16FW value) + { + DirectBuffer buffer = value.value(); + kafkaHeadersRW.item(h -> + { + h.nameLen(key.sizeof()); + h.name(key); + h.valueLen(value.length()); + h.value(buffer, 0, buffer.capacity()); + }); + } + + private void addHeader( + OctetsFW key, + DirectBuffer buffer, + int offset, + int length) + { + kafkaHeadersRW.item(h -> + { + h.nameLen(key.sizeof()); + h.name(key); + h.valueLen(length); + h.value(buffer, offset, length); + }); + } + + private void addHeader(String16FW key, String16FW value) + { + DirectBuffer keyBuffer = key.value(); + DirectBuffer valueBuffer = value.value(); + kafkaHeadersRW.item(h -> + { + h.nameLen(key.length()); + h.name(keyBuffer, 0, keyBuffer.capacity()); + h.valueLen(value.length()); + h.value(valueBuffer, 0, valueBuffer.capacity()); + }); + } + } + + private static int indexOfByte( + DirectBuffer buffer, + int offset, + int limit, + byte value) + { + int byteAt = -1; + for (int index = offset; index < limit; index++) + { + if (buffer.getByte(index) == value) + { + byteAt = index; + break; + } + } + return byteAt; + } + + private static boolean isSetWillFlag( + int flags) + { + return (flags & MqttSessionFlags.WILL.value() << 1) != 0; + } + + private static boolean isSetCleanStart( + int flags) + { + return (flags & MqttSessionFlags.CLEAN_START.value() << 1) != 0; + } + + private abstract class KafkaSessionStream + { + protected MessageConsumer kafka; + protected final long originId; + protected final long routedId; + protected long initialId; + protected long replyId; + protected final MqttSessionProxy delegate; + + protected int state; + + protected long initialSeq; + protected long initialAck; + protected int initialMax; + + protected long replySeq; + protected long replyAck; + protected int replyMax; + protected int replyPad; + + private KafkaSessionStream( + long originId, + long routedId, + MqttSessionProxy delegate) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void doKafkaBeginIfNecessary( + long traceId, + long authorization, + long affinity) + { + if (!MqttKafkaState.initialOpening(state)) + { + doKafkaBegin(traceId, authorization, affinity); + } + } + + protected final void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + protected final void cancelExpirySignal( + long authorization, + long traceId) + { + String16FW expirySignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(delegate.clientId.asString() + EXPIRY_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + Flyweight expirySignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(expirySignalKey.length()) + .value(expirySignalKey.value(), 0, expirySignalKey.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(EXPIRY_SIGNAL_NAME_OCTETS.sizeof()) + .value(EXPIRY_SIGNAL_NAME_OCTETS))) + .build(); + + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, + null, expirySignalKafkaDataEx); + } + + protected final void sendExpirySignal( + long authorization, + long traceId, + Flyweight payload) + { + String16FW expirySignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(delegate.clientId.asString() + EXPIRY_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + Flyweight expirySignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(expirySignalKey.length()) + .value(expirySignalKey.value(), 0, expirySignalKey.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(EXPIRY_SIGNAL_NAME_OCTETS.sizeof()) + .value(EXPIRY_SIGNAL_NAME_OCTETS))) + .build(); + + + doKafkaData(traceId, authorization, 0, payload.sizeof(), DATA_FLAG_COMPLETE, + payload, expirySignalKafkaDataEx); + } + + private void sendWillSignal( + long traceId, + long authorization) + { + String16FW willSignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(delegate.clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + Flyweight willSignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(willSignalKey.length()) + .value(willSignalKey.value(), 0, willSignalKey.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) + .value(WILL_SIGNAL_NAME_OCTETS))) + .build(); + + final MqttSessionSignalFW willSignal = + mqttSessionSignalRW.wrap(sessionSignalBuffer, 0, sessionSignalBuffer.capacity()) + .will(w -> w + .instanceId(instanceId.instanceId()) + .clientId(delegate.clientId) + .delay(delegate.delay) + .deliverAt(supplyTime.getAsLong() + delegate.delay) + .lifetimeId(delegate.lifetimeId) + .willId(delegate.willId)) + .build(); + + doKafkaData(traceId, authorization, 0, willSignal.sizeof(), DATA_FLAG_COMPLETE, + willSignal, willSignalKafkaDataEx); + } + + protected void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + Flyweight payload, + Flyweight extension) + { + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + final int length = limit - offset; + + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, buffer, offset, length, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, extension); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + if (isSetWillFlag(delegate.sessionFlags)) + { + Flyweight mqttBeginEx = mqttSessionBeginExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder + .flags(delegate.sessionFlags) + .expiry((int) TimeUnit.MILLISECONDS.toSeconds(delegate.sessionExpiryMillis)) + .qosMax(MQTT_KAFKA_MAX_QOS) + .packetSizeMax(packetSizeMax) + .capabilities(MQTT_KAFKA_CAPABILITIES) + .clientId(delegate.clientId)) + .build(); + + delegate.doMqttBegin(traceId, authorization, affinity, mqttBeginEx); + } + doKafkaWindow(traceId, authorization, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + delegate.doMqttAbort(traceId, authorization); + } + else + { + handleKafkaData(data); + } + } + + protected abstract void doKafkaBegin( + long traceId, + long authorization, + long affinity); + + protected abstract void handleKafkaData( + DataFW data); + + protected void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + } + + protected void onKafkaEnd( + EndFW end) + { + } + + protected void onKafkaFlush( + FlushFW flush) + { + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + protected void sendMigrateSignal( + long traceId, + long authorization) + { + Flyweight kafkaMigrateDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(delegate.clientIdMigrate.length()) + .value(delegate.clientIdMigrate.value(), 0, delegate.clientIdMigrate.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(c -> c.nameLen(SENDER_ID_NAME.length()) + .name(SENDER_ID_NAME.value(), 0, SENDER_ID_NAME.length()) + .valueLen(delegate.sessionId.length()) + .value(delegate.sessionId.value(), 0, delegate.sessionId.length()))) + .build(); + + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, + EMPTY_OCTETS, kafkaMigrateDataEx); + } + + protected void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + + final OctetsFW extension = reset.extension(); + final ExtensionFW resetEx = extension.get(extensionRO::tryWrap); + final KafkaResetExFW kafkaResetEx = + resetEx != null && resetEx.typeId() == kafkaTypeId ? extension.get(kafkaResetExRO::tryWrap) : null; + + Flyweight mqttResetEx = EMPTY_OCTETS; + + final String16FW consumerId = kafkaResetEx != null ? kafkaResetEx.consumerId() : null; + + if (consumerId != null) + { + mqttResetEx = mqttResetExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .serverRef(consumerId) + .build(); + } + + delegate.doMqttReset(traceId, mqttResetEx); + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, replyPad, 0, capabilities); + } + } + + private final class KafkaSessionSignalStream extends KafkaSessionStream + { + private KafkaSessionSignalStream( + long originId, + long routedId, + MqttSessionProxy delegate) + { + super(originId, routedId, delegate); + } + + @Override + protected void doKafkaBegin(long traceId, long authorization, long affinity) + { + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.sessionsTopic, null, delegate.clientIdMigrate, + delegate.sessionId, serverRef, KafkaCapabilities.PRODUCE_AND_FETCH); + } + + @Override + protected void handleKafkaData(DataFW data) + { + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + final OctetsFW extension = data.extension(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key() : null; + + if (delegate.group != null && key != null) + { + delegate.group.doKafkaFlush(traceId, authorization, budgetId, reserved); + } + } + + @Override + protected void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + if (!wasOpen) + { + final long routedId = delegate.session.routedId; + + delegate.group = new KafkaGroupStream(originId, routedId, delegate); + delegate.group.doKafkaBegin(traceId, authorization, 0); + + sendMigrateSignal(traceId, authorization); + } + } + } + + private final class KafkaSessionStateProxy extends KafkaSessionStream + { + private KafkaSessionStateProxy( + long originId, + long routedId, + MqttSessionProxy delegate) + { + super(originId, routedId, delegate); + } + + @Override + protected void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + state = MqttKafkaState.openingInitial(state); + + KafkaCapabilities capabilities = isSetWillFlag(delegate.sessionFlags) ? + KafkaCapabilities.PRODUCE_ONLY : KafkaCapabilities.PRODUCE_AND_FETCH; + kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.sessionsTopic, delegate.clientId, delegate.clientIdMigrate, + delegate.sessionId, serverRef, capabilities); + } + + @Override + protected void handleKafkaData( + DataFW data) + { + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + final int flags = data.flags(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key() : null; + + if (key != null && payload != null) + { + int keyLen = key.length(); + if (keyLen == delegate.clientId.length()) + { + MqttSessionStateFW sessionState = + mqttSessionStateRO.wrap(payload.buffer(), payload.offset(), payload.limit()); + delegate.doMqttData(traceId, authorization, budgetId, reserved, flags, sessionState); + } + else if (keyLen == delegate.clientIdMigrate.length()) + { + delegate.group.doKafkaFlush(traceId, authorization, budgetId, reserved); + } + } + } + + @Override + protected void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + if (!wasOpen) + { + if (!isSetCleanStart(delegate.sessionFlags)) + { + cancelWillSignal(authorization, traceId); + } + cancelExpirySignal(authorization, traceId); // expiry cancellation + + final MqttSessionSignalFW expirySignal = + mqttSessionSignalRW.wrap(sessionSignalBuffer, 0, sessionSignalBuffer.capacity()) + .expiry(w -> w + .instanceId(instanceId.instanceId()) + .clientId(delegate.clientId) + .delay(delegate.sessionExpiryMillis) + .expireAt(MqttTime.UNKNOWN.value())) + .build(); + sendExpirySignal(authorization, traceId, expirySignal); // expire later + } + + delegate.doMqttWindow(authorization, traceId, budgetId, padding + delegate.sessionPadding, capabilities); + } + + private void cancelWillSignal( + long authorization, + long traceId) + { + String16FW willSignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(delegate.clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + Flyweight willSignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(willSignalKey.length()) + .value(willSignalKey.value(), 0, willSignalKey.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) + .value(WILL_SIGNAL_NAME_OCTETS))) + .build(); + + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, + null, willSignalKafkaDataEx); + } + + @Override + protected void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + delegate.doMqttData(traceId, authorization, budgetId, 0, DATA_FLAG_COMPLETE, EMPTY_OCTETS); + } + + @Override + protected void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttEnd(traceId, authorization); + } + } + + private final class KafkaFetchWillSignalStream extends KafkaSessionStream + { + private KafkaFetchWillSignalStream( + long originId, + long routedId, + MqttSessionProxy delegate) + { + super(originId, routedId, delegate); + } + + @Override + protected void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + if (!MqttKafkaState.initialOpening(state)) + { + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.sessionsTopic, delegate.clientId, serverRef); + } + } + + @Override + protected void handleKafkaData( + DataFW data) + { + final OctetsFW extension = data.extension(); + final OctetsFW payload = data.payload(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key() : null; + + if (key != null && payload != null) + { + MqttSessionSignalFW sessionSignal = + mqttSessionSignalRO.wrap(payload.buffer(), payload.offset(), payload.limit()); + if (sessionSignal != null) + { + delegate.lifetimeId = sessionSignal.will().lifetimeId().asString(); + } + } + } + + @Override + protected void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + delegate.session.doKafkaEnd(traceId, authorization); + final long routedId = delegate.session.routedId; + + delegate.session = new KafkaSessionSignalStream(originId, routedId, delegate); + delegate.session.doKafkaBeginIfNecessary(traceId, authorization, 0); + } + } + + private final class KafkaGroupStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSessionProxy delegate; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaGroupStream( + long originId, + long routedId, + MqttSessionProxy delegate) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newGroupStream(this::onGroupMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.clientId, delegate.sessionExpiryMillis); + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved) + { + initialSeq = delegate.initialSeq; + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, EMPTY_OCTETS); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void onGroupMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + final OctetsFW extension = flush.extension(); + final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); + final KafkaFlushExFW kafkaFlushEx = + flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; + final KafkaGroupFlushExFW kafkaGroupDataEx = + kafkaFlushEx != null && kafkaFlushEx.kind() == KafkaFlushExFW.KIND_GROUP ? kafkaFlushEx.group() : null; + final String16FW leaderId = kafkaGroupDataEx != null ? kafkaGroupDataEx.leaderId() : null; + final String16FW memberId = kafkaGroupDataEx != null ? kafkaGroupDataEx.memberId() : null; + final int members = kafkaGroupDataEx != null ? kafkaGroupDataEx.members().fieldCount() : 0; + + if (leaderId.equals(memberId)) + { + if (members > 1) + { + delegate.session.sendMigrateSignal(traceId, authorization); + delegate.session.sendWillSignal(traceId, authorization); + delegate.session.doKafkaEnd(traceId, authorization); + doKafkaEnd(traceId, authorization); + } + else + { + delegate.session.doKafkaEnd(traceId, authorization); + final long routedId = delegate.session.routedId; + delegate.session = new KafkaSessionStateProxy(originId, routedId, delegate); + delegate.session.doKafkaBeginIfNecessary(traceId, authorization, 0); + } + } + + if (!MqttKafkaState.initialClosed(state)) + { + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, EMPTY_OCTETS, EMPTY_OCTETS); + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + final OctetsFW extension = begin.extension(); + + int sessionExpiryMillisInRange = delegate.sessionExpiryMillis; + if (extension.sizeof() > 0) + { + final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::tryWrap); + + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_GROUP; + final KafkaGroupBeginExFW kafkaGroupBeginEx = kafkaBeginEx.group(); + + sessionExpiryMillisInRange = kafkaGroupBeginEx.timeout(); + } + + if (delegate.sessionExpiryMillis != sessionExpiryMillisInRange) + { + delegate.sessionExpiryMillis = sessionExpiryMillisInRange; + } + + Flyweight mqttBeginEx = mqttSessionBeginExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder + .flags(delegate.sessionFlags) + .expiry((int) TimeUnit.MILLISECONDS.toSeconds(delegate.sessionExpiryMillis)) + .qosMax(MQTT_KAFKA_MAX_QOS) + .packetSizeMax(packetSizeMax) + .capabilities(MQTT_KAFKA_CAPABILITIES) + .clientId(delegate.clientId)) + .build(); + + delegate.doMqttBegin(traceId, authorization, affinity, mqttBeginEx); + doKafkaWindow(traceId, authorization, 0, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + delegate.doMqttAbort(traceId, authorization); + } + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttEnd(traceId, authorization); + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + + delegate.doMqttReset(traceId, EMPTY_OCTETS); + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + } + + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + OctetsFW payload, + Flyweight extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + DirectBuffer buffer, + int index, + int length, + Flyweight extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(buffer, index, length) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private MessageConsumer newKafkaStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW sessionsTopicName, + String16FW clientId, + String16FW clientIdMigrate, + String16FW sessionId, + String serverRef, + KafkaCapabilities capabilities) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> + { + m.capabilities(c -> c.set(capabilities)); + m.topic(sessionsTopicName); + m.groupId(MQTT_CLIENTS_GROUP_ID); + m.consumerId(serverRef); + if (clientId != null) + { + m.partitionsItem(p -> + p.partitionId(KafkaOffsetType.HISTORICAL.value()) + .partitionOffset(KafkaOffsetType.HISTORICAL.value())); + m.filtersItem(f -> f.conditionsItem(ci -> + ci.key(kb -> kb.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())))); + } + m.filtersItem(f -> + { + f.conditionsItem(ci -> + ci.key(kb -> kb.length(clientIdMigrate.length()) + .value(clientIdMigrate.value(), 0, clientIdMigrate.length()))); + f.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(SENDER_ID_NAME.length()) + .name(SENDER_ID_NAME.value(), 0, SENDER_ID_NAME.length()) + .valueLen(sessionId.length()) + .value(sessionId.value(), 0, sessionId.length()))))); + }); + m.ackMode(b -> b.set(KAFKA_DEFAULT_ACK_MODE)); + }) + .build(); + + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private MessageConsumer newKafkaStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW topic) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.capabilities(c -> c.set(KafkaCapabilities.PRODUCE_ONLY)) + .topic(topic) + .partitionsItem(p -> p.partitionId(-1).partitionOffset(-2L)) + .ackMode(b -> b.set(KAFKA_DEFAULT_ACK_MODE))) + .build(); + + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private MessageConsumer newKafkaStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW topic, + String16FW clientId, + String serverRef) + { + String16FW key = new String16FW(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX); + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> + m.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)) + .topic(topic) + .groupId(MQTT_CLIENTS_GROUP_ID) + .consumerId(serverRef) + .partitionsItem(p -> + p.partitionId(KafkaOffsetType.HISTORICAL.value()) + .partitionOffset(KafkaOffsetType.HISTORICAL.value())) + .filtersItem(f -> + f.conditionsItem(c -> + c.key(k -> k.length(key.length()) + .value(key.value(), 0, key.length())))) + .evaluation(b -> b.set(KafkaEvaluation.EAGER))) + .build(); + + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private MessageConsumer newKafkaStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW clientId, + String16FW lifetimeId, + String16FW topic) + { + String16FW key = new String16FW(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId.asString()); + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> + m.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)) + .topic(topic) + .partitionsItem(p -> + p.partitionId(KafkaOffsetType.HISTORICAL.value()) + .partitionOffset(KafkaOffsetType.HISTORICAL.value())) + .filtersItem(f -> + f.conditionsItem(c -> + c.key(k -> k.length(key.length()) + .value(key.value(), 0, key.length())))) + .evaluation(b -> b.set(KafkaEvaluation.EAGER))) + .build(); + + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + + private MessageConsumer newSignalStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW sessionsTopicName) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> + m.capabilities(c -> c.set(KafkaCapabilities.PRODUCE_AND_FETCH)) + .topic(sessionsTopicName) + .groupId(MQTT_CLIENTS_GROUP_ID) + .consumerId(serverRef) + .filtersItem(f -> + f.conditionsItem(c -> c.header(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) + .value(WILL_SIGNAL_NAME_OCTETS)))) + .filtersItem(f -> + f.conditionsItem(c -> c.header(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(EXPIRY_SIGNAL_NAME_OCTETS.sizeof()) + .value(EXPIRY_SIGNAL_NAME_OCTETS)))) + .ackMode(b -> b.set(KAFKA_DEFAULT_ACK_MODE))) + .build(); + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private MessageConsumer newGroupStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW clientId, + int sessionExpiryMs) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .group(g -> g.groupId(clientId).protocol(GROUP_PROTOCOL).timeout(sessionExpiryMs)) + .build(); + + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding, + int minimum, + int capabilities) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .minimum(minimum) + .capabilities(capabilities) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + Flyweight extension) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } +} diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaState.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaState.java similarity index 100% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaState.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaState.java diff --git a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaStreamFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaStreamFactory.java similarity index 76% rename from incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaStreamFactory.java rename to runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaStreamFactory.java index 73aa200e57..6aaf100848 100644 --- a/incubator/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaStreamFactory.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaStreamFactory.java @@ -19,9 +19,23 @@ public interface MqttKafkaStreamFactory extends BindingHandler { - void attach( - BindingConfig binding); + default void attach( + BindingConfig binding) + { + } - void detach( - long bindingId); + default void detach( + long bindingId) + { + } + + default void onAttached( + long binding) + { + } + + default void onDetached( + long bindingId) + { + } } diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java new file mode 100644 index 0000000000..853b280aa3 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java @@ -0,0 +1,1970 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; + + +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPublishFlags.RETAIN; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSubscribeFlags.NO_LOCAL; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSubscribeFlags.RETAIN_AS_PUBLISHED; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSubscribeFlags.SEND_RETAINED; +import static io.aklivity.zilla.runtime.engine.buffer.BufferPool.NO_SLOT; + + +import java.util.ArrayList; +import java.util.List; +import java.util.function.LongFunction; +import java.util.function.LongUnaryOperator; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.IntArrayList; +import org.agrona.collections.Long2ObjectHashMap; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaHeaderHelper; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaCapabilities; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaConditionFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaEvaluation; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaHeaderFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaOffsetType; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaSkip; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttTopicFilterFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Varuint32FW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.codec.MqttSubscribeMessageFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSubscribeBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSubscribeFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; + +public class MqttKafkaSubscribeFactory implements MqttKafkaStreamFactory +{ + private static final String MQTT_TYPE_NAME = "mqtt"; + private static final String KAFKA_TYPE_NAME = "kafka"; + private static final String MQTT_SINGLE_LEVEL_WILDCARD = "+"; + private static final String MQTT_MULTI_LEVEL_WILDCARD = "#"; + private static final int NO_LOCAL_FLAG = 1 << NO_LOCAL.ordinal(); + private static final int SEND_RETAIN_FLAG = 1 << SEND_RETAINED.ordinal(); + private static final int RETAIN_FLAG = 1 << RETAIN.ordinal(); + private static final int RETAIN_AS_PUBLISHED_FLAG = 1 << RETAIN_AS_PUBLISHED.ordinal(); + public static final int DATA_FIN_FLAG = 0x03; + private final OctetsFW emptyRO = new OctetsFW().wrap(new UnsafeBuffer(0L, 0), 0, 0); + private final BeginFW beginRO = new BeginFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final AbortFW abortRO = new AbortFW(); + private final FlushFW flushRO = new FlushFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + + private final WindowFW windowRO = new WindowFW(); + private final ResetFW resetRO = new ResetFW(); + + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final MqttSubscribeMessageFW.Builder mqttSubscribeMessageRW = new MqttSubscribeMessageFW.Builder(); + + private final ExtensionFW extensionRO = new ExtensionFW(); + private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); + private final MqttFlushExFW mqttFlushExRO = new MqttFlushExFW(); + private final KafkaDataExFW kafkaDataExRO = new KafkaDataExFW(); + private final KafkaHeaderFW kafkaHeaderRO = new KafkaHeaderFW(); + private final MqttSubscribeMessageFW mqttSubscribeMessageRO = new MqttSubscribeMessageFW(); + + private final MqttDataExFW.Builder mqttDataExRW = new MqttDataExFW.Builder(); + + private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); + private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); + private final Array32FW.Builder sendRetainedFiltersRW = + new Array32FW.Builder<>(new MqttTopicFilterFW.Builder(), new MqttTopicFilterFW()); + + private final Array32FW.Builder subscriptionIdsRW = + new Array32FW.Builder<>(new Varuint32FW.Builder(), new Varuint32FW()); + + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final MutableDirectBuffer subscriptionIdsBuffer; + private final MutableDirectBuffer retainFilterBuffer; + private final BindingHandler streamFactory; + private final BufferPool bufferPool; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final int mqttTypeId; + private final int kafkaTypeId; + private final LongFunction supplyBinding; + private final MqttKafkaHeaderHelper helper; + + public MqttKafkaSubscribeFactory( + MqttKafkaConfiguration config, + EngineContext context, + LongFunction supplyBinding) + { + this.mqttTypeId = context.supplyTypeId(MQTT_TYPE_NAME); + this.kafkaTypeId = context.supplyTypeId(KAFKA_TYPE_NAME); + this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.subscriptionIdsBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.retainFilterBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.streamFactory = context.streamFactory(); + this.bufferPool = context.bufferPool(); + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyBinding = supplyBinding; + this.helper = new MqttKafkaHeaderHelper(); + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer mqtt) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + + final MqttKafkaBindingConfig binding = supplyBinding.apply(routedId); + + final MqttKafkaRouteConfig resolved = binding != null ? + binding.resolve(authorization) : null; + + MessageConsumer newStream = null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + final String16FW kafkaMessagesTopic = binding.messagesTopic(); + final String16FW kafkaRetainedTopic = binding.retainedTopic(); + newStream = new MqttSubscribeProxy(mqtt, originId, routedId, initialId, resolvedId, + kafkaMessagesTopic, kafkaRetainedTopic)::onMqttMessage; + } + + return newStream; + } + + private final class MqttSubscribeProxy + { + private final MessageConsumer mqtt; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final KafkaMessagesProxy messages; + private final KafkaRetainedProxy retained; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + private long replyBud; + private int mqttSharedBudget; + + private final IntArrayList messagesSubscriptionIds; + private final IntArrayList retainedSubscriptionIds; + private final Long2ObjectHashMap retainAsPublished; + private final List retainedSubscriptions; + private String16FW clientId; + private boolean retainAvailable; + + private MqttSubscribeProxy( + MessageConsumer mqtt, + long originId, + long routedId, + long initialId, + long resolvedId, + String16FW kafkaMessagesTopic, + String16FW kafkaRetainedTopic) + { + this.mqtt = mqtt; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.messagesSubscriptionIds = new IntArrayList(); + this.retainedSubscriptionIds = new IntArrayList(); + this.retainedSubscriptions = new ArrayList<>(); + this.retainAsPublished = new Long2ObjectHashMap<>(); + this.messages = new KafkaMessagesProxy(originId, resolvedId, kafkaMessagesTopic, this); + this.retained = new KafkaRetainedProxy(originId, resolvedId, kafkaRetainedTopic, this); + } + + private void onMqttMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onMqttBegin(begin); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onMqttFlush(flush); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onMqttData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onMqttEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onMqttAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onMqttReset(reset); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onMqttWindow(window); + break; + } + } + + private void onMqttBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + state = MqttKafkaState.openingInitial(state); + + assert initialAck <= initialSeq; + + final OctetsFW extension = begin.extension(); + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + + assert mqttBeginEx.kind() == MqttBeginExFW.KIND_SUBSCRIBE; + final MqttSubscribeBeginExFW mqttSubscribeBeginEx = mqttBeginEx.subscribe(); + + clientId = newString16FW(mqttSubscribeBeginEx.clientId()); + + Array32FW filters = mqttSubscribeBeginEx.filters(); + filters.forEach(filter -> + { + int subscriptionId = (int) filter.subscriptionId(); + if (!messagesSubscriptionIds.contains(subscriptionId)) + { + messagesSubscriptionIds.add(subscriptionId); + } + if ((filter.flags() & SEND_RETAIN_FLAG) != 0) + { + retainAvailable = true; + } + }); + + final List retainedFilters = new ArrayList<>(); + if (retainAvailable) + { + filters.forEach(filter -> + { + final boolean sendRetained = (filter.flags() & SEND_RETAIN_FLAG) != 0; + if (sendRetained) + { + retainedFilters.add(new Subscription( + (int) filter.subscriptionId(), newString16FW(filter.pattern()), filter.qos(), filter.flags())); + } + }); + } + if (retainAvailable && !retainedFilters.isEmpty()) + { + retained.doKafkaBegin(traceId, authorization, affinity, retainedFilters); + } + messages.doKafkaBegin(traceId, authorization, affinity, filters); + } + + private void onMqttFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + final OctetsFW extension = flush.extension(); + final MqttFlushExFW mqttFlushEx = extension.get(mqttFlushExRO::tryWrap); + + assert mqttFlushEx.kind() == MqttFlushExFW.KIND_SUBSCRIBE; + final MqttSubscribeFlushExFW mqttSubscribeFlushEx = mqttFlushEx.subscribe(); + + Array32FW filters = mqttSubscribeFlushEx.filters(); + messagesSubscriptionIds.clear(); + + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.fetch(f -> + { + f.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); + filters.forEach(filter -> + { + if ((filter.flags() & SEND_RETAIN_FLAG) != 0) + { + retainAvailable = true; + } + f.filtersItem(fi -> + { + final int subscriptionId = (int) filter.subscriptionId(); + fi.conditionsItem(ci -> + { + if (!messagesSubscriptionIds.contains(subscriptionId)) + { + messagesSubscriptionIds.add(subscriptionId); + } + buildHeaders(ci, filter.pattern().asString()); + }); + + final boolean noLocal = (filter.flags() & NO_LOCAL_FLAG) != 0; + if (noLocal) + { + final DirectBuffer valueBuffer = clientId.value(); + fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(helper.kafkaLocalHeaderName.sizeof()) + .name(helper.kafkaLocalHeaderName) + .valueLen(valueBuffer.capacity()) + .value(valueBuffer, 0, valueBuffer.capacity()))))); + } + }); + }); + })) + .build(); + + messages.doKafkaFlush(traceId, authorization, budgetId, reserved, kafkaFlushEx); + + if (retainAvailable) + { + final List retainedFilters = new ArrayList<>(); + filters.forEach(filter -> + { + final boolean sendRetained = (filter.flags() & SEND_RETAIN_FLAG) != 0; + if (sendRetained) + { + retainedFilters.add(new Subscription( + (int) filter.subscriptionId(), newString16FW(filter.pattern()), filter.qos(), filter.flags())); + final boolean rap = (filter.flags() & RETAIN_AS_PUBLISHED_FLAG) != 0; + retainAsPublished.put((int) filter.subscriptionId(), rap); + } + }); + + retainedSubscriptions.removeIf(rf -> !filters.anyMatch(f -> f.pattern().equals(rf.filter))); + if (!retainedFilters.isEmpty()) + { + if (MqttKafkaState.initialOpened(retained.state) && !MqttKafkaState.initialClosed(retained.state)) + { + retained.doKafkaFlush(traceId, authorization, budgetId, reserved, retainedFilters); + } + else + { + final List newRetainedFilters = new ArrayList<>(); + retainedFilters.forEach(subscription -> + { + if (!retainedSubscriptions.contains(subscription)) + { + newRetainedFilters.add(subscription); + } + }); + retained.doKafkaBegin(traceId, authorization, 0, newRetainedFilters); + } + } + } + } + + private void onMqttData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + doMqttReset(traceId); + + messages.doKafkaAbort(traceId, authorization); + if (retainAvailable) + { + retained.doKafkaAbort(traceId, authorization); + } + } + + + private void onMqttEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttKafkaState.closeInitial(state); + + assert initialAck <= initialSeq; + + + messages.doKafkaEnd(traceId, initialSeq, authorization); + if (retainAvailable) + { + retained.doKafkaEnd(traceId, initialSeq, authorization); + } + } + + private void onMqttAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttKafkaState.closeInitial(state); + + assert initialAck <= initialSeq; + + + messages.doKafkaAbort(traceId, authorization); + if (retainAvailable) + { + retained.doKafkaAbort(traceId, authorization); + } + } + + private void onMqttReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final int maximum = reset.maximum(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + + messages.doKafkaReset(traceId); + if (retainAvailable) + { + retained.doKafkaReset(traceId); + } + } + + private void onMqttWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyPad = padding; + state = MqttKafkaState.openReply(state); + this.replyBud = window.budgetId(); + + assert replyAck <= replySeq; + + mqttSharedBudget = replyMax - (int)(replySeq - replyAck); + + if (retainAvailable) + { + retained.doKafkaWindow(traceId, authorization, budgetId, padding, capabilities); + } + else if (messages.messageSlotOffset != messages.messageSlotLimit) + { + messages.flushData(traceId, authorization, budgetId); + } + messages.doKafkaWindow(traceId, authorization, budgetId, padding, capabilities); + } + + private void doMqttBegin( + long traceId, + long authorization, + long affinity) + { + state = MqttKafkaState.openingReply(state); + + doBegin(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity); + } + + private void doMqttData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + replySeq += reserved; + + assert replySeq <= replyAck + replyMax; + } + + private void doMqttFlush( + long traceId, + long authorization, + long budgetId, + int reserved) + { + replySeq = messages.replySeq; + + doFlush(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, reserved, emptyRO); + } + + private void doMqttAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.replyClosed(state)) + { + replySeq = messages.replySeq; + state = MqttKafkaState.closeReply(state); + + doAbort(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); + } + } + + private void doMqttEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.replyClosed(state)) + { + replySeq = messages.replySeq; + state = MqttKafkaState.closeReply(state); + + doEnd(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization); + } + } + + private void doMqttWindow( + long authorization, + long traceId, + long budgetId, + int padding, + int capabilities) + { + initialAck = messages.initialAck; + initialMax = messages.initialMax; + + doWindow(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, padding, 0, capabilities); + } + + private void doMqttReset( + long traceId) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId); + } + } + + public int replyPendingAck() + { + return (int)(replySeq - replyAck); + } + + private int replyWindow() + { + return replyMax - replyPendingAck(); + } + } + + final class KafkaMessagesProxy + { + private final String16FW topic; + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSubscribeProxy mqtt; + + private int dataSlot = NO_SLOT; + private int messageSlotLimit; + private int messageSlotOffset; + private int messageSlotReserved; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaMessagesProxy( + long originId, + long routedId, + String16FW topic, + MqttSubscribeProxy mqtt) + { + this.originId = originId; + this.routedId = routedId; + this.topic = topic; + this.mqtt = mqtt; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + Array32FW filters) + { + if (!MqttKafkaState.initialOpening(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, mqtt.clientId, topic, filters, KafkaOffsetType.LIVE); + } + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + initialSeq = mqtt.initialSeq; + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, extension); + } + + private void doKafkaEnd( + long traceId, + long sequence, + long authorization) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + mqtt.doMqttBegin(traceId, authorization, affinity); + doKafkaWindow(traceId, authorization, mqtt.replyBud, mqtt.replyPad, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + mqtt.doMqttAbort(traceId, authorization); + } + else + { + final int flags = data.flags(); + final int length = data.length(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final OctetsFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key().value() : null; + final long filters = kafkaMergedDataEx != null ? kafkaMergedDataEx.filters() : 0; + + if (key != null) + { + String topicName = kafkaMergedDataEx.key().value() + .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)); + helper.visit(kafkaMergedDataEx); + + final MqttDataExFW mqttSubscribeDataEx = mqttDataExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .subscribe(b -> + { + b.topic(topicName); + + int flag = 0; + subscriptionIdsRW.wrap(subscriptionIdsBuffer, 0, subscriptionIdsBuffer.capacity()); + for (int i = 0; i < mqtt.messagesSubscriptionIds.size(); i++) + { + if (((filters >> i) & 1) == 1) + { + long subscriptionId = mqtt.messagesSubscriptionIds.get(i); + subscriptionIdsRW.item(si -> si.set((int) subscriptionId)); + } + } + b.flags(flag); + b.subscriptionIds(subscriptionIdsRW.build()); + if (helper.timeout != -1) + { + b.expiryInterval(helper.timeout / 1000); + } + if (helper.contentType != null) + { + b.contentType( + helper.contentType.buffer(), helper.contentType.offset(), helper.contentType.sizeof()); + } + if (helper.format != null) + { + b.format(f -> f.set(MqttPayloadFormat.valueOf(helper.format))); + } + if (helper.replyTo != null) + { + b.responseTopic( + helper.replyTo.buffer(), helper.replyTo.offset(), helper.replyTo.sizeof()); + } + if (helper.correlation != null) + { + b.correlation(c -> c.bytes(helper.correlation)); + } + + final DirectBuffer buffer = kafkaMergedDataEx.buffer(); + final int limit = kafkaMergedDataEx.limit(); + helper.userPropertiesOffsets.forEach(o -> + { + final KafkaHeaderFW header = kafkaHeaderRO.wrap(buffer, o, limit); + final OctetsFW name = header.name(); + final OctetsFW value = header.value(); + if (value != null) + { + b.propertiesItem(pi -> pi + .key(name.buffer(), name.offset(), name.sizeof()) + .value(value.buffer(), value.offset(), value.sizeof())); + } + }); + }).build(); + + if (!MqttKafkaState.initialOpened(mqtt.retained.state) || + MqttKafkaState.replyClosed(mqtt.retained.state)) + { + mqtt.doMqttData(traceId, authorization, budgetId, reserved, flags, payload, mqttSubscribeDataEx); + mqtt.mqttSharedBudget -= length; + } + else + { + if (dataSlot == NO_SLOT) + { + dataSlot = bufferPool.acquire(initialId); + } + + if (dataSlot == NO_SLOT) + { + cleanup(traceId, authorization); + } + + + final MutableDirectBuffer dataBuffer = bufferPool.buffer(dataSlot); + Flyweight message = mqttSubscribeMessageRW.wrap(dataBuffer, messageSlotLimit, dataBuffer.capacity()) + .extension(mqttSubscribeDataEx.buffer(), mqttSubscribeDataEx.offset(), mqttSubscribeDataEx.sizeof()) + .payload(payload) + .build(); + + messageSlotLimit = message.limit(); + messageSlotReserved += reserved; + } + } + } + } + + private void flushData( + long traceId, + long authorization, + long budgetId) + { + int length = Math.max(Math.min(mqtt.replyWindow() - mqtt.replyPad, messageSlotLimit - messageSlotOffset), 0); + int reserved = length + mqtt.replyPad; + if (length > 0) + { + final MutableDirectBuffer dataBuffer = bufferPool.buffer(dataSlot); + // TODO: data fragmentation + while (messageSlotOffset != length) + { + final MqttSubscribeMessageFW message = mqttSubscribeMessageRO.wrap(dataBuffer, messageSlotOffset, + dataBuffer.capacity()); + mqtt.doMqttData(traceId, authorization, budgetId, reserved, DATA_FIN_FLAG, message.payload(), + message.extension()); + + messageSlotOffset += message.sizeof(); + } + if (messageSlotOffset == messageSlotLimit) + { + bufferPool.release(dataSlot); + dataSlot = NO_SLOT; + messageSlotLimit = 0; + messageSlotOffset = 0; + } + } + } + + private void cleanup( + long traceId, + long authorization) + { + mqtt.doMqttAbort(traceId, authorization); + doKafkaAbort(traceId, authorization); + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + mqtt.doMqttEnd(traceId, authorization); + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + mqtt.doMqttFlush(traceId, authorization, budgetId, reserved); + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + mqtt.doMqttAbort(traceId, authorization); + } + + private void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert acknowledge >= mqtt.initialAck; + assert maximum >= mqtt.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + mqtt.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= mqtt.initialAck; + + mqtt.initialAck = acknowledge; + + assert mqtt.initialAck <= mqtt.initialSeq; + + mqtt.doMqttReset(traceId); + } + + private void doKafkaReset( + long traceId) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + if (MqttKafkaState.replyOpening(state)) + { + final int replyWin = replyMax - (int) (replySeq - replyAck); + final int newReplyWin = mqtt.mqttSharedBudget; + + final int replyCredit = newReplyWin - replyWin; + + if (replyCredit > 0) + { + final int replyNoAck = (int) (replySeq - replyAck - messageSlotReserved); + final int replyAcked = Math.min(replyNoAck, replyCredit); + replyAck += replyAcked; + assert replyAck <= replySeq; + + replyMax = newReplyWin + (int) (replySeq - replyAck - messageSlotReserved); + assert replyMax >= 0; + + if (messageSlotReserved > 0 && dataSlot == NO_SLOT) + { + replyAck += messageSlotReserved; + messageSlotReserved = 0; + } + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + } + } + } + + final class KafkaRetainedProxy + { + private final String16FW topic; + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSubscribeProxy mqtt; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaRetainedProxy( + long originId, + long routedId, + String16FW topic, + MqttSubscribeProxy mqtt) + { + this.originId = originId; + this.routedId = routedId; + this.topic = topic; + this.mqtt = mqtt; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + List newRetainedFilters) + { + state = 0; + replySeq = 0; + replyAck = 0; + replyMax = 0; + + sendRetainedFiltersRW.wrap(retainFilterBuffer, 0, retainFilterBuffer.capacity()); + + newRetainedFilters.forEach(f -> + { + final int subscriptionId = f.id; + if (!mqtt.retainedSubscriptionIds.contains(subscriptionId)) + { + mqtt.retainedSubscriptionIds.add(subscriptionId); + } + sendRetainedFiltersRW.item(fb -> fb + .subscriptionId(subscriptionId).qos(f.qos).flags(f.flags).pattern(f.filter)); + final boolean rap = (f.flags & RETAIN_AS_PUBLISHED_FLAG) != 0; + mqtt.retainAsPublished.put(f.id, rap); + }); + mqtt.retainedSubscriptions.addAll(newRetainedFilters); + + Array32FW retainedFilters = sendRetainedFiltersRW.build(); + + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + + state = MqttKafkaState.openingInitial(state); + + kafka = + newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, mqtt.clientId, topic, retainedFilters, KafkaOffsetType.HISTORICAL); + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + List retainedFiltersList) + { + initialSeq = mqtt.initialSeq; + + sendRetainedFiltersRW.wrap(retainFilterBuffer, 0, retainFilterBuffer.capacity()); + + retainedFiltersList.forEach(f -> + { + final int subscriptionId = f.id; + if (!mqtt.retainedSubscriptionIds.contains(subscriptionId)) + { + mqtt.retainedSubscriptionIds.add(subscriptionId); + } + sendRetainedFiltersRW.item(fb -> fb + .subscriptionId(subscriptionId).qos(f.qos).flags(f.flags).pattern(f.filter)); + final boolean rap = (f.flags & RETAIN_AS_PUBLISHED_FLAG) != 0; + mqtt.retainAsPublished.put(f.id, rap); + }); + + Array32FW retainedFilters = sendRetainedFiltersRW.build(); + + final KafkaFlushExFW retainedKafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.fetch(f -> + { + f.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); + retainedFilters.forEach(filter -> + { + f.filtersItem(fi -> + { + final int subscriptionId = (int) filter.subscriptionId(); + fi.conditionsItem(ci -> + { + if (!mqtt.messagesSubscriptionIds.contains(subscriptionId)) + { + mqtt.messagesSubscriptionIds.add(subscriptionId); + } + buildHeaders(ci, filter.pattern().asString()); + }); + }); + }); + })) + .build(); + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, retainedKafkaFlushEx); + } + + private void doKafkaEnd( + long traceId, + long sequence, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = replySeq + sequence; + replyAck = replySeq + acknowledge; + replyMax = maximum; + + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + mqtt.doMqttBegin(traceId, authorization, affinity); + doKafkaWindow(traceId, authorization, mqtt.replyBud, mqtt.replyPad, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + mqtt.doMqttAbort(traceId, authorization); + } + else + { + final int flags = data.flags(); + final int length = data.length(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final OctetsFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.key().value() : null; + final long filters = kafkaMergedDataEx != null ? kafkaMergedDataEx.filters() : 0; + + if (key != null) + { + String topicName = kafkaMergedDataEx.key().value() + .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)); + helper.visit(kafkaMergedDataEx); + final Flyweight mqttSubscribeDataEx = mqttDataExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .subscribe(b -> + { + b.topic(topicName); + + int flag = 0; + subscriptionIdsRW.wrap(subscriptionIdsBuffer, 0, subscriptionIdsBuffer.capacity()); + for (int i = 0; i < mqtt.retainedSubscriptionIds.size(); i++) + { + if (((filters >> i) & 1) == 1) + { + long subscriptionId = mqtt.retainedSubscriptionIds.get(i); + if (mqtt.retainAsPublished.getOrDefault(subscriptionId, false)) + { + flag |= RETAIN_FLAG; + } + subscriptionIdsRW.item(si -> si.set((int) subscriptionId)); + } + } + b.flags(flag); + b.subscriptionIds(subscriptionIdsRW.build()); + if (helper.timeout != -1) + { + b.expiryInterval(helper.timeout / 1000); + } + if (helper.contentType != null) + { + b.contentType( + helper.contentType.buffer(), helper.contentType.offset(), helper.contentType.sizeof()); + } + if (helper.format != null) + { + b.format(f -> f.set(MqttPayloadFormat.valueOf(helper.format))); + } + if (helper.replyTo != null) + { + b.responseTopic( + helper.replyTo.buffer(), helper.replyTo.offset(), helper.replyTo.sizeof()); + } + if (helper.correlation != null) + { + b.correlation(c -> c.bytes(helper.correlation)); + } + + final DirectBuffer buffer = kafkaMergedDataEx.buffer(); + final int limit = kafkaMergedDataEx.limit(); + helper.userPropertiesOffsets.forEach(o -> + { + final KafkaHeaderFW header = kafkaHeaderRO.wrap(buffer, o, limit); + final OctetsFW name = header.name(); + final OctetsFW value = header.value(); + if (value != null) + { + b.propertiesItem(pi -> pi + .key(name.buffer(), name.offset(), name.sizeof()) + .value(value.buffer(), value.offset(), value.sizeof())); + } + }); + }).build(); + + mqtt.doMqttData(traceId, authorization, budgetId, reserved, flags, payload, mqttSubscribeDataEx); + + mqtt.mqttSharedBudget -= length; + } + } + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + mqtt.messages.flushData(traceId, authorization, mqtt.replyBud); + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + mqtt.retainedSubscriptionIds.clear(); + doKafkaEnd(traceId, sequence, authorization); + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + mqtt.doMqttAbort(traceId, authorization); + } + + private void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + + assert acknowledge <= sequence; + assert acknowledge >= mqtt.initialAck; + assert maximum >= mqtt.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + mqtt.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= mqtt.initialAck; + + mqtt.initialAck = acknowledge; + + assert mqtt.initialAck <= mqtt.initialSeq; + + mqtt.doMqttReset(traceId); + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + if (MqttKafkaState.replyOpening(state) && + !MqttKafkaState.replyClosing(state)) + { + final int replyWin = replyMax - (int) (replySeq - replyAck); + final int newReplyWin = mqtt.mqttSharedBudget; + + final int replyCredit = newReplyWin - replyWin; + + if (replyCredit > 0) + { + final int replyNoAck = (int) (replySeq - replyAck); + final int replyAcked = Math.min(replyNoAck, replyCredit); + + replyAck += replyAcked; + assert replyAck <= replySeq; + + replyMax = newReplyWin + (int) (replySeq - replyAck); + assert replyMax >= 0; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + } + } + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int flags, + int reserved, + OctetsFW payload, + Flyweight extension) + { + final DataFW frame = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .flags(flags) + .budgetId(budgetId) + .reserved(reserved) + .payload(payload) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(frame.typeId(), frame.buffer(), frame.offset(), frame.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private MessageConsumer newKafkaStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW clientId, + String16FW topic, + Array32FW filters, + KafkaOffsetType offsetType) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> + { + m.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); + m.topic(topic); + m.partitionsItem(p -> + p.partitionId(offsetType.value()) + .partitionOffset(offsetType.value())); + filters.forEach(filter -> + + m.filtersItem(f -> + { + f.conditionsItem(ci -> buildHeaders(ci, filter.pattern().asString())); + boolean noLocal = (filter.flags() & NO_LOCAL_FLAG) != 0; + if (noLocal) + { + final DirectBuffer valueBuffer = clientId.value(); + f.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(helper.kafkaLocalHeaderName.sizeof()) + .name(helper.kafkaLocalHeaderName) + .valueLen(valueBuffer.capacity()) + .value(valueBuffer, 0, valueBuffer.capacity()))))); + } + })); + m.evaluation(b -> b.set(KafkaEvaluation.EAGER)); + }) + .build(); + + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void buildHeaders( + KafkaConditionFW.Builder conditionBuilder, + String pattern) + { + String[] headers = pattern.split("/"); + conditionBuilder.headers(hb -> + { + hb.nameLen(helper.kafkaFilterHeaderName.sizeof()); + hb.name(helper.kafkaFilterHeaderName); + for (String header : headers) + { + if (header.equals(MQTT_SINGLE_LEVEL_WILDCARD)) + { + hb.valuesItem(vi -> vi.skip(sb -> sb.set(KafkaSkip.SKIP))); + } + else if (header.equals(MQTT_MULTI_LEVEL_WILDCARD)) + { + hb.valuesItem(vi -> vi.skip(sb -> sb.set(KafkaSkip.SKIP_MANY))); + } + else + { + final DirectBuffer valueBuffer = new String16FW(header).value(); + hb.valuesItem(vi -> vi.value(vb -> vb.length(valueBuffer.capacity()) + .value(valueBuffer, 0, valueBuffer.capacity()))); + + } + } + }); + } + + private void doWindow( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding, + int minimum, + int capabilities) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .minimum(minimum) + .capabilities(capabilities) + .build(); + + sender.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .build(); + + sender.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + private String16FW newString16FW( + String16FW value) + { + return new String16FW().wrap(value.buffer(), value.offset(), value.limit()); + } + + private static final class Subscription + { + private final int id; + private final String16FW filter; + private final int qos; + private final int flags; + + Subscription( + int id, + String16FW filter, + int qos, + int flags) + { + this.id = id; + this.filter = filter; + this.qos = qos; + this.flags = flags; + } + } +} diff --git a/runtime/binding-mqtt-kafka/src/main/moditect/module-info.java b/runtime/binding-mqtt-kafka/src/main/moditect/module-info.java new file mode 100644 index 0000000000..056d27a5d6 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/moditect/module-info.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +module io.aklivity.zilla.runtime.binding.mqtt.kafka +{ + requires io.aklivity.zilla.runtime.engine; + + exports io.aklivity.zilla.runtime.binding.mqtt.kafka.config; + + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi + with io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaBindingFactorySpi; + + provides io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi + with io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaConditionConfigAdapter; + + provides io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi + with io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaOptionsConfigAdapter; + +} diff --git a/incubator/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi b/runtime/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi similarity index 100% rename from incubator/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi rename to runtime/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi diff --git a/incubator/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi b/runtime/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi similarity index 100% rename from incubator/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi rename to runtime/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi diff --git a/runtime/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi b/runtime/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi new file mode 100644 index 0000000000..50a9b1d8b4 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi @@ -0,0 +1 @@ +io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaOptionsConfigAdapter diff --git a/runtime/binding-mqtt-kafka/src/main/zilla/internal.idl b/runtime/binding-mqtt-kafka/src/main/zilla/internal.idl new file mode 100644 index 0000000000..a77267637b --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/zilla/internal.idl @@ -0,0 +1,28 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + + scope internal + { + scope codec + { + struct MqttSubscribeMessage + { + uint32 extensionLength; + octets[extensionLength] extension; + uint32 payloadLength; + octets[payloadLength] payload; + } + } + } diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfigurationTest.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfigurationTest.java new file mode 100644 index 0000000000..c962645286 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfigurationTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal; + + +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.INSTANCE_ID; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.LIFETIME_ID; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.SESSION_ID; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.TIME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.WILL_AVAILABLE; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.WILL_ID; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration.WILL_STREAM_RECONNECT_DELAY; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MqttKafkaConfigurationTest +{ + public static final String TIME_NAME = "zilla.binding.mqtt.kafka.time"; + public static final String WILL_AVAILABLE_NAME = "zilla.binding.mqtt.kafka.will.available"; + public static final String WILL_STREAM_RECONNECT_DELAY_NAME = "zilla.binding.mqtt.kafka.will.stream.reconnect"; + public static final String SESSION_ID_NAME = "zilla.binding.mqtt.kafka.session.id"; + public static final String WILL_ID_NAME = "zilla.binding.mqtt.kafka.will.id"; + public static final String LIFETIME_ID_NAME = "zilla.binding.mqtt.kafka.lifetime.id"; + public static final String INSTANCE_ID_NAME = "zilla.binding.mqtt.kafka.instance.id"; + + @Test + public void shouldVerifyConstants() + { + assertEquals(TIME.name(), TIME_NAME); + assertEquals(WILL_AVAILABLE.name(), WILL_AVAILABLE_NAME); + assertEquals(WILL_STREAM_RECONNECT_DELAY.name(), WILL_STREAM_RECONNECT_DELAY_NAME); + assertEquals(SESSION_ID.name(), SESSION_ID_NAME); + assertEquals(WILL_ID.name(), WILL_ID_NAME); + assertEquals(LIFETIME_ID.name(), LIFETIME_ID_NAME); + assertEquals(INSTANCE_ID.name(), INSTANCE_ID_NAME); + } +} diff --git a/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapterTest.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapterTest.java similarity index 95% rename from incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapterTest.java rename to runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapterTest.java index 00c4d8b488..6c4eb05319 100644 --- a/incubator/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapterTest.java +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaConditionConfigAdapterTest.java @@ -26,6 +26,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.config.MqttKafkaConditionConfig; + public class MqttKafkaConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfigAdapterTest.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfigAdapterTest.java new file mode 100644 index 0000000000..edfdce43e3 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaOptionsConfigAdapterTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; + +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; + +import org.junit.Before; +import org.junit.Test; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; + +public class MqttKafkaOptionsConfigAdapterTest +{ + private Jsonb jsonb; + + @Before + public void initJson() + { + JsonbConfig config = new JsonbConfig() + .withAdapters(new MqttKafkaOptionsConfigAdapter()); + jsonb = JsonbBuilder.create(config); + } + + @Test + public void shouldReadOptions() + { + String text = + "{" + + "\"server\":\"mqtt-1.example.com:1883\"," + + "\"topics\":" + + "{" + + "\"sessions\":\"sessions\"," + + "\"messages\":\"messages\"," + + "\"retained\":\"retained\"," + + "}" + + "}"; + + MqttKafkaOptionsConfig options = jsonb.fromJson(text, MqttKafkaOptionsConfig.class); + + assertThat(options, not(nullValue())); + assertThat(options.topics, not(nullValue())); + assertThat(options.topics.sessions.asString(), equalTo("sessions")); + assertThat(options.topics.messages.asString(), equalTo("messages")); + assertThat(options.topics.retained.asString(), equalTo("retained")); + assertThat(options.serverRef, equalTo("mqtt-1.example.com:1883")); + } + + @Test + public void shouldWriteOptions() + { + MqttKafkaOptionsConfig options = new MqttKafkaOptionsConfig( + new MqttKafkaTopicsConfig( + new String16FW("sessions"), + new String16FW("messages"), + new String16FW("retained")), "mqtt-1.example.com:1883"); + + String text = jsonb.toJson(options); + + assertThat(text, not(nullValue())); + assertThat(text, equalTo( + "{" + + "\"server\":\"mqtt-1.example.com:1883\"," + + "\"topics\":" + + "{" + + "\"sessions\":\"sessions\"," + + "\"messages\":\"messages\"," + + "\"retained\":\"retained\"" + + "}" + + "}")); + } +} diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java new file mode 100644 index 0000000000..8dd6772f7d --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java @@ -0,0 +1,262 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.WILL_AVAILABLE_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class MqttKafkaPublishProxyIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("mqtt", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt") + .addScriptRoot("kafka", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config") + .external("kafka0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.client.sent.abort/client", + "${kafka}/publish.client.sent.abort/server"}) + public void shouldReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.client.sent.reset/client", + "${kafka}/publish.client.sent.reset/server"}) + public void shouldReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.server.sent.abort/client", + "${kafka}/publish.server.sent.abort/server"}) + public void shouldReceiveServerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.server.sent.flush/client", + "${kafka}/publish.server.sent.flush/server"}) + public void shouldReceiveServerSentFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.server.sent.reset/client", + "${kafka}/publish.server.sent.reset/server"}) + public void shouldReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.server.sent.data/client", + "${kafka}/publish.server.sent.data/server"}) + public void shouldAbortWhenServerSentData() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.retained.server.sent.abort/client", + "${kafka}/publish.retained.server.sent.abort/server"}) + public void shouldPublishRetainedThenReceiveServerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.retained.server.sent.flush/client", + "${kafka}/publish.retained.server.sent.flush/server"}) + public void shouldPublishRetainedThenReceiveServerSentFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.retained.server.sent.reset/client", + "${kafka}/publish.retained.server.sent.reset/server"}) + public void shouldPublishRetainedThenReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.retained.server.sent.data/client", + "${kafka}/publish.retained.server.sent.data/server"}) + public void shouldPublishRetainedThenAbortWhenServerSentData() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.one.message/client", + "${kafka}/publish.one.message/server"}) + public void shouldSendOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.options.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.one.message/client", + "${kafka}/publish.one.message.changed.topic.name/server"}) + public void shouldSendOneMessageWithChangedTopicName() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.retained/client", + "${kafka}/publish.retained/server"}) + public void shouldPublishRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.empty.message/client", + "${kafka}/publish.empty.message/server"}) + public void shouldSendEmptyMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.multiple.messages/client", + "${kafka}/publish.multiple.messages/server"}) + public void shouldSendMultipleMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.multiple.clients/client", + "${kafka}/publish.multiple.clients/server"}) + public void shouldSendMultipleClients() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.with.user.property/client", + "${kafka}/publish.with.user.property/server"}) + public void shouldSendWithUserProperty() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.with.user.properties.distinct/client", + "${kafka}/publish.with.user.properties.distinct/server"}) + public void shouldSendWithDistinctUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.with.user.properties.repeated/client", + "${kafka}/publish.with.user.properties.repeated/server"}) + public void shouldSendWithRepeatedUserProperties() throws Exception + { + k3po.finish(); + } + +} diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionProxyIT.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionProxyIT.java new file mode 100644 index 0000000000..350186e2c4 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionProxyIT.java @@ -0,0 +1,381 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.INSTANCE_ID_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.LIFETIME_ID_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.SESSION_ID_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.TIME_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.WILL_AVAILABLE_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.WILL_ID_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.WILL_STREAM_RECONNECT_DELAY_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class MqttKafkaSessionProxyIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("mqtt", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt") + .addScriptRoot("kafka", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + public final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configure(SESSION_ID_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplySessionId") + .configure(INSTANCE_ID_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplyInstanceId") + .configure(TIME_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplyTime") + .configure(LIFETIME_ID_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplyLifetimeId") + .configure(WILL_ID_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplyWillId") + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config") + .external("kafka0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.connect.override.max.session.expiry/client", + "${kafka}/session.connect.override.max.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiryTooBig() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.connect.override.min.session.expiry/client", + "${kafka}/session.connect.override.min.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiryTooSmall() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.abort.reconnect.non.clean.start/client", + "${kafka}/session.abort.reconnect.non.clean.start/server"}) + public void shouldReconnectNonCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.client.takeover/client", + "${kafka}/session.client.takeover/server"}) + public void shouldTakeOverSession() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.exists.clean.start/client", + "${kafka}/session.exists.clean.start/server"}) + public void shouldRemoveSessionAtCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.subscribe/client", + "${kafka}/session.subscribe/server"}) + public void shouldSubscribeSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.subscribe.via.session.state/client", + "${kafka}/session.subscribe.via.session.state/server"}) + public void shouldReceiveMessageSubscribedViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.unsubscribe.after.subscribe/client", + "${kafka}/session.unsubscribe.after.subscribe/server"}) + public void shouldUnsubscribeAndUpdateSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.unsubscribe.via.session.state/client", + "${kafka}/session.unsubscribe.via.session.state/server"}) + public void shouldUnsubscribeViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.client.sent.reset/client", + "${kafka}/session.client.sent.reset/server"}) + public void shouldSessionStreamReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.server.sent.reset/client", + "${kafka}/session.server.sent.reset/server"}) + public void shouldSessionStreamReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/session.server.sent.reset/client", + "${kafka}/session.group.server.sent.reset/server"}) + public void shouldGroupStreamReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = SESSION_ID_NAME, + value = "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplySessionId") + @Specification({ + "${mqtt}/session.redirect/client", + "${kafka}/session.redirect/server"}) + public void shouldRedirect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.close.expire.session.state/client", + "${kafka}/session.close.expire.session.state/server"}) + public void shouldExpireSessionOnClose() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.abort.expire.session.state/client", + "${kafka}/session.abort.expire.session.state/server"}) + public void shouldExpireSessionOnAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${kafka}/session.cancel.session.expiry/server"}) + public void shouldCancelSessionExpiry() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${kafka}/session.session.expiry.fragmented/server"}) + public void shouldDecodeSessionExpirySignalFragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.will.message.normal.disconnect/client", + "${kafka}/session.will.message.normal.disconnect/server"}) + public void shouldNotSendWillMessageOnNormalDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.will.message.clean.start/client", + "${kafka}/session.will.message.clean.start/server"}) + public void shouldGenerateLifeTimeIdOnCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.will.message.abort.deliver.will/client", + "${kafka}/session.will.message.abort.deliver.will/server"}) + public void shouldSendWillMessageOnAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.will.message.abort.deliver.will/client", + "${kafka}/session.will.message.will.id.mismatch.skip.delivery/server"}) + public void shouldNotSendWillMessageOnWillIdMismatch() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.will.message.abort.deliver.will.retain/client", + "${kafka}/session.will.message.abort.deliver.will.retain/server"}) + public void shouldSaveWillMessageAsRetain() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${mqtt}/session.will.message.takeover.deliver.will/client", + "${kafka}/session.will.message.takeover.deliver.will/server"}) + public void shouldDeliverWillMessageOnSessionTakeover() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Specification({ + "${kafka}/session.will.message.cancel.delivery/server"}) + public void shouldCancelWillDelivery() throws Exception + { + k3po.start(); + Thread.sleep(1000); + k3po.notifyBarrier("ONE_SECOND_ELAPSED"); + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_STREAM_RECONNECT_DELAY_NAME, value = "1") + @Specification({ + "${kafka}/session.will.stream.end.reconnect/server"}) + public void shouldReconnectWillStreamOnKafkaEnd() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_STREAM_RECONNECT_DELAY_NAME, value = "1") + @Specification({ + "${kafka}/session.will.stream.abort.reconnect/server"}) + public void shouldReconnectWillStreamOnKafkaAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_STREAM_RECONNECT_DELAY_NAME, value = "1") + @Specification({ + "${kafka}/session.will.stream.reset.reconnect/server"}) + public void shouldReconnectWillStreamOnKafkaReset() throws Exception + { + k3po.finish(); + } + + public static String supplySessionId() + { + return "sender-1"; + } + + public static String supplyWillId() + { + return "d252a6bd-abb5-446a-b0f7-d0a3d8c012e2"; + } + + public static String supplyLifetimeId() + { + return "1e6a1eb5-810a-459d-a12c-a6fa08f228d1"; + } + + public static String supplyInstanceId() + { + return "zilla-1"; + } + + public static long supplyTime() + { + return 1000L; + } +} diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeProxyIT.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeProxyIT.java new file mode 100644 index 0000000000..7eecb79af7 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeProxyIT.java @@ -0,0 +1,417 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; + +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.WILL_AVAILABLE_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class MqttKafkaSubscribeProxyIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("mqtt", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt") + .addScriptRoot("kafka", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config") + .external("kafka0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.client.sent.abort/client", + "${kafka}/subscribe.client.sent.abort/server"}) + public void shouldReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.client.sent.data/client", + "${kafka}/subscribe.client.sent.data/server"}) + public void shouldAbortWhenClientSentData() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.client.sent.reset/client", + "${kafka}/subscribe.client.sent.reset/server"}) + public void shouldReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.server.sent.abort/client", + "${kafka}/subscribe.server.sent.abort/server"}) + public void shouldReceiveServerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.server.sent.flush/client", + "${kafka}/subscribe.server.sent.flush/server"}) + public void shouldReceiveServerSentFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.server.sent.reset/client", + "${kafka}/subscribe.server.sent.reset/server"}) + public void shouldReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.retained.server.sent.abort/client", + "${kafka}/subscribe.retained.server.sent.abort/server"}) + public void shouldReceiveServerSentRetainedAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.retained.server.sent.reset/client", + "${kafka}/subscribe.retained.server.sent.reset/server"}) + public void shouldReceiveServerSentRetainedReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.one.message/client", + "${kafka}/subscribe.one.message/server"}) + public void shouldReceiveOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.options.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.one.message/client", + "${kafka}/subscribe.one.message.changed.topic.name/server"}) + public void shouldReceiveOneMessageWithChangedTopicName() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.multiple.message/client", + "${kafka}/subscribe.multiple.message/server"}) + public void shouldReceiveMultipleMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.retain.as.published/client", + "${kafka}/subscribe.retain/server"}) + public void shouldReceiveRetainAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.retain/client", + "${kafka}/subscribe.retain/server"}) + public void shouldReceiveRetainedNoRetainAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.filter.change.retain/client", + "${kafka}/subscribe.filter.change.retain/server"}) + public void shouldReceiveRetainedAfterFilterChange() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.filter.change.retain/client", + "${kafka}/subscribe.filter.change.retain.buffer/server"}) + public void shouldReceiveRetainedAfterFilterChangeBufferMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.deferred.filter.change.retain/client", + "${kafka}/subscribe.deferred.filter.change.retain/server"}) + public void shouldReceiveRetainedAfterDeferredFilterChange() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.filter.change.retain.resubscribe/client", + "${kafka}/subscribe.filter.change.retain.resubscribe/server"}) + public void shouldReceiveRetainedAfterResubscribe() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.one.message.receive.response.topic.and.correlation.data/client", + "${kafka}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) + public void shouldReceiveCorrelationData() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.one.message.user.properties.unaltered/client", + "${kafka}/subscribe.one.message.user.properties.unaltered/server"}) + public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.publish.no.local/client", + "${kafka}/subscribe.publish.no.local/server"}) + public void shouldNotReceiveLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.receive.message.overlapping.wildcard/client", + "${kafka}/subscribe.receive.message.overlapping.wildcard/server"}) + public void shouldReceiveMessageOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.receive.message.wildcard/client", + "${kafka}/subscribe.receive.message.wildcard/server"}) + public void shouldReceiveOneMessageWithPatternTopic() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filter.multi.level.wildcard/client", + "${kafka}/subscribe.topic.filter.multi.level.wildcard/server"}) + public void shouldFilterMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filter.single.and.multi.level.wildcard/client", + "${kafka}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) + public void shouldFilterSingleAndMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filter.single.level.wildcard/client", + "${kafka}/subscribe.topic.filter.single.level.wildcard/server"}) + public void shouldFilterSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filter.two.single.level.wildcard/client", + "${kafka}/subscribe.topic.filter.two.single.level.wildcard/server"}) + public void shouldFilterTwoSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filters.aggregated.both.exact/client", + "${kafka}/subscribe.topic.filters.aggregated.both.exact/server"}) + public void shouldFilterAggregatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", + "${kafka}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) + public void shouldFilterAggregatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filters.isolated.both.exact/client", + "${kafka}/subscribe.topic.filters.isolated.both.exact/server"}) + public void shouldFilterIsolatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filters.isolated.exact.and.wildcard/client", + "${kafka}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) + public void shouldFilterIsolatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/subscribe.topic.filters.overlapping.wildcards/client", + "${kafka}/subscribe.topic.filters.overlapping.wildcards/server"}) + public void shouldFilterOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/unsubscribe.after.subscribe/client", + "${kafka}/unsubscribe.after.subscribe/server"}) + public void shouldAcknowledge() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/unsubscribe.topic.filter.single/client", + "${kafka}/unsubscribe.topic.filter.single/server"}) + public void shouldAcknowledgeSingleTopicFilter() throws Exception + { + k3po.finish(); + } +} diff --git a/incubator/binding-mqtt.spec/COPYRIGHT b/runtime/binding-mqtt/COPYRIGHT similarity index 100% rename from incubator/binding-mqtt.spec/COPYRIGHT rename to runtime/binding-mqtt/COPYRIGHT diff --git a/incubator/binding-mqtt.spec/LICENSE b/runtime/binding-mqtt/LICENSE similarity index 100% rename from incubator/binding-mqtt.spec/LICENSE rename to runtime/binding-mqtt/LICENSE diff --git a/incubator/binding-mqtt/NOTICE b/runtime/binding-mqtt/NOTICE similarity index 100% rename from incubator/binding-mqtt/NOTICE rename to runtime/binding-mqtt/NOTICE diff --git a/incubator/binding-mqtt.spec/NOTICE.template b/runtime/binding-mqtt/NOTICE.template similarity index 100% rename from incubator/binding-mqtt.spec/NOTICE.template rename to runtime/binding-mqtt/NOTICE.template diff --git a/incubator/binding-mqtt.spec/mvnw b/runtime/binding-mqtt/mvnw similarity index 100% rename from incubator/binding-mqtt.spec/mvnw rename to runtime/binding-mqtt/mvnw diff --git a/incubator/binding-mqtt.spec/mvnw.cmd b/runtime/binding-mqtt/mvnw.cmd similarity index 100% rename from incubator/binding-mqtt.spec/mvnw.cmd rename to runtime/binding-mqtt/mvnw.cmd diff --git a/runtime/binding-mqtt/pom.xml b/runtime/binding-mqtt/pom.xml new file mode 100644 index 0000000000..647f5e7508 --- /dev/null +++ b/runtime/binding-mqtt/pom.xml @@ -0,0 +1,235 @@ + + + + 4.0.0 + + io.aklivity.zilla + runtime + 0.9.52 + ../pom.xml + + + binding-mqtt + zilla::runtime::binding-mqtt + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + 11 + 11 + 0.69 + 3 + + + + + ${project.groupId} + binding-mqtt.spec + ${project.version} + provided + + + ${project.groupId} + engine + ${project.version} + provided + + + ${project.groupId} + engine + test-jar + ${project.version} + test + + + junit + junit + test + + + org.hamcrest + hamcrest-library + test + + + org.mockito + mockito-core + test + + + org.kaazing + k3po.junit + test + + + org.kaazing + k3po.lang + test + + + org.openjdk.jmh + jmh-core + test + + + org.openjdk.jmh + jmh-generator-annprocess + test + + + + + + + org.jasig.maven + maven-notice-plugin + + + ${project.groupId} + flyweight-maven-plugin + ${project.version} + + core mqtt protocol + io.aklivity.zilla.runtime.binding.mqtt.internal.types + + + + + generate + + + + + + com.mycila + license-maven-plugin + + + maven-checkstyle-plugin + + + maven-dependency-plugin + + + process-resources + + unpack + + + + + ${project.groupId} + binding-mqtt.spec + + + ^\Qio/aklivity/zilla/specs/binding/mqtt/\E + io/aklivity/zilla/runtime/binding/mqtt/internal/ + + + + + io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json + ${project.build.directory}/classes + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.moditect + moditect-maven-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + org.kaazing + k3po-maven-plugin + + + ${project.groupId} + engine + ${project.version} + test-jar + + + ${project.groupId} + engine + ${project.version} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.jacoco + jacoco-maven-plugin + + + io/aklivity/zilla/runtime/binding/mqtt/internal/types/**/*.class + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + ${jacoco.coverage.ratio} + + + CLASS + MISSEDCOUNT + ${jacoco.missed.count} + + + + + + + + io.gatling + maven-shade-plugin + + + + org.agrona:agrona + io.aklivity.zilla:engine + org.openjdk.jmh:jmh-core + net.sf.jopt-simple:jopt-simple + org.apache.commons:commons-math3 + commons-cli:commons-cli + com.github.biboudis:jmh-profilers + + + + + + + diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttConditionConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttConditionConfig.java new file mode 100644 index 0000000000..7ce8a7fdcd --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttConditionConfig.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.config; + +import java.util.List; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; + +public final class MqttConditionConfig extends ConditionConfig +{ + public final List sessions; + public final List subscribes; + public final List publishes; + + public static MqttConditionConfigBuilder builder() + { + return new MqttConditionConfigBuilder<>(MqttConditionConfig.class::cast); + } + + public static MqttConditionConfigBuilder builder( + Function mapper) + { + return new MqttConditionConfigBuilder<>(mapper); + } + + MqttConditionConfig( + List sessions, + List subscribes, + List publishes) + { + this.sessions = sessions; + this.subscribes = subscribes; + this.publishes = publishes; + } +} + diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttConditionConfigBuilder.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttConditionConfigBuilder.java new file mode 100644 index 0000000000..551e2230ba --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttConditionConfigBuilder.java @@ -0,0 +1,85 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.config; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class MqttConditionConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private final List session; + private final List subscribe; + private final List publish; + + MqttConditionConfigBuilder( + Function mapper) + { + this.mapper = mapper; + this.session = new ArrayList<>(); + this.subscribe = new ArrayList<>(); + this.publish = new ArrayList<>(); + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public MqttConditionConfigBuilder session( + MqttSessionConfig session) + { + this.session.add(session); + return this; + } + + public MqttConditionConfigBuilder subscribe( + MqttSubscribeConfig subscribe) + { + this.subscribe.add(subscribe); + return this; + } + + public MqttSubscribeConfigBuilder> subscribe() + { + return new MqttSubscribeConfigBuilder<>(this::subscribe); + } + + public MqttConditionConfigBuilder publish( + MqttPublishConfig publish) + { + this.publish.add(publish); + return this; + } + + public MqttPublishConfigBuilder> publish() + { + return new MqttPublishConfigBuilder<>(this::publish); + } + + @Override + public T build() + { + return mapper.apply(new MqttConditionConfig(session, subscribe, publish)); + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttPublishConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttPublishConfig.java new file mode 100644 index 0000000000..5168244ffb --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttPublishConfig.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.config; + +public class MqttPublishConfig +{ + public final String topic; + + public MqttPublishConfig( + String topic) + { + this.topic = topic; + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttPublishConfigBuilder.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttPublishConfigBuilder.java new file mode 100644 index 0000000000..0c74378307 --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttPublishConfigBuilder.java @@ -0,0 +1,52 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public class MqttPublishConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String topic; + + public MqttPublishConfigBuilder(Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public MqttPublishConfigBuilder topic( + String topic) + { + this.topic = topic; + return this; + } + + @Override + public T build() + { + return mapper.apply(new MqttPublishConfig(topic)); + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSessionConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSessionConfig.java new file mode 100644 index 0000000000..2f8ed7c73f --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSessionConfig.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.config; + +public class MqttSessionConfig +{ + public final String clientId; + + public MqttSessionConfig( + String clientId) + { + this.clientId = clientId; + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSubscribeConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSubscribeConfig.java new file mode 100644 index 0000000000..909cd75929 --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSubscribeConfig.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.config; + +public class MqttSubscribeConfig +{ + public final String topic; + + public MqttSubscribeConfig( + String topic) + { + this.topic = topic; + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSubscribeConfigBuilder.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSubscribeConfigBuilder.java new file mode 100644 index 0000000000..f413e8d17c --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/config/MqttSubscribeConfigBuilder.java @@ -0,0 +1,52 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public class MqttSubscribeConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String topic; + + public MqttSubscribeConfigBuilder(Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public MqttSubscribeConfigBuilder topic( + String topic) + { + this.topic = topic; + return this; + } + + @Override + public T build() + { + return mapper.apply(new MqttSubscribeConfig(topic)); + } +} diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java similarity index 100% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java similarity index 91% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java index eae9c10a13..dddd632e52 100644 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java @@ -15,11 +15,13 @@ */ package io.aklivity.zilla.runtime.binding.mqtt.internal; +import static io.aklivity.zilla.runtime.engine.config.KindConfig.CLIENT; import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; import java.util.EnumMap; import java.util.Map; +import io.aklivity.zilla.runtime.binding.mqtt.internal.stream.MqttClientFactory; import io.aklivity.zilla.runtime.binding.mqtt.internal.stream.MqttServerFactory; import io.aklivity.zilla.runtime.binding.mqtt.internal.stream.MqttStreamFactory; import io.aklivity.zilla.runtime.engine.EngineContext; @@ -38,7 +40,7 @@ final class MqttBindingContext implements BindingContext { final EnumMap factories = new EnumMap<>(KindConfig.class); factories.put(SERVER, new MqttServerFactory(config, context)); - //factories.put(CLIENT, new MqttClientFactory(config, context)); + factories.put(CLIENT, new MqttClientFactory(config, context)); this.factories = factories; } diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingFactorySpi.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingFactorySpi.java similarity index 100% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingFactorySpi.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingFactorySpi.java diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfiguration.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfiguration.java new file mode 100644 index 0000000000..cf23bf107f --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfiguration.java @@ -0,0 +1,179 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.function.IntSupplier; + +import org.agrona.LangUtil; + +import io.aklivity.zilla.runtime.engine.Configuration; + +public class MqttConfiguration extends Configuration +{ + private static final ConfigurationDef MQTT_CONFIG; + public static final LongPropertyDef CONNECT_TIMEOUT; + public static final LongPropertyDef CONNACK_TIMEOUT; + public static final LongPropertyDef PUBLISH_TIMEOUT; + public static final ShortPropertyDef KEEP_ALIVE_MINIMUM; + public static final ShortPropertyDef KEEP_ALIVE_MAXIMUM; + public static final BytePropertyDef MAXIMUM_QOS; + public static final BooleanPropertyDef RETAIN_AVAILABLE; + public static final ShortPropertyDef TOPIC_ALIAS_MAXIMUM; + public static final BooleanPropertyDef WILDCARD_SUBSCRIPTION; + public static final BooleanPropertyDef SUBSCRIPTION_IDENTIFIERS; + public static final BooleanPropertyDef SHARED_SUBSCRIPTION; + public static final BooleanPropertyDef NO_LOCAL; + public static final IntPropertyDef SESSION_EXPIRY_GRACE_PERIOD; + public static final PropertyDef CLIENT_ID; + public static final PropertyDef SUBSCRIPTION_ID; + public static final int GENERATED_SUBSCRIPTION_ID_MASK = 0x70; + + static + { + final ConfigurationDef config = new ConfigurationDef("zilla.binding.mqtt"); + PUBLISH_TIMEOUT = config.property("publish.timeout", TimeUnit.SECONDS.toSeconds(30)); + CONNECT_TIMEOUT = config.property("connect.timeout", TimeUnit.SECONDS.toSeconds(3)); + CONNACK_TIMEOUT = config.property("connack.timeout", TimeUnit.SECONDS.toSeconds(3)); + //TODO: better default values? + KEEP_ALIVE_MINIMUM = config.property("keep.alive.minimum", (short) 10); + KEEP_ALIVE_MAXIMUM = config.property("keep.alive.maximum", (short) 1000); + MAXIMUM_QOS = config.property("maximum.qos", (byte) 0); + RETAIN_AVAILABLE = config.property("retain.available", true); + TOPIC_ALIAS_MAXIMUM = config.property("topic.alias.maximum", (short) 0); + WILDCARD_SUBSCRIPTION = config.property("wildcard.subscription.available", true); + SUBSCRIPTION_IDENTIFIERS = config.property("subscription.identifiers.available", true); + SHARED_SUBSCRIPTION = config.property("shared.subscription.available", false); + NO_LOCAL = config.property("no.local", true); + SESSION_EXPIRY_GRACE_PERIOD = config.property("session.expiry.grace.period", 30); + CLIENT_ID = config.property("client.id"); + SUBSCRIPTION_ID = config.property(IntSupplier.class, "subscription.id", + MqttConfiguration::decodeIntSupplier, MqttConfiguration::defaultSubscriptionId); + MQTT_CONFIG = config; + } + + public MqttConfiguration( + Configuration config) + { + super(MQTT_CONFIG, config); + } + + public long publishTimeout() + { + return PUBLISH_TIMEOUT.get(this); + } + + public long connectTimeout() + { + return CONNECT_TIMEOUT.get(this); + } + + public long connackTimeout() + { + return CONNACK_TIMEOUT.get(this); + } + + public boolean retainAvailable() + { + return RETAIN_AVAILABLE.get(this); + } + + public short keepAliveMinimum() + { + return KEEP_ALIVE_MINIMUM.get(this); + } + + public short keepAliveMaximum() + { + return KEEP_ALIVE_MAXIMUM.get(this); + } + + public byte maximumQos() + { + return MAXIMUM_QOS.get(this); + } + + public short topicAliasMaximum() + { + return TOPIC_ALIAS_MAXIMUM.get(this); + } + + public boolean noLocal() + { + return NO_LOCAL.get(this); + } + + public int sessionExpiryGracePeriod() + { + return SESSION_EXPIRY_GRACE_PERIOD.get(this); + } + + public String clientId() + { + return CLIENT_ID.get(this); + } + + + public IntSupplier subscriptionId() + { + return SUBSCRIPTION_ID.get(this); + } + + private static IntSupplier decodeIntSupplier( + String fullyQualifiedMethodName) + { + IntSupplier supplier = null; + + try + { + MethodType signature = MethodType.methodType(int.class); + String[] parts = fullyQualifiedMethodName.split("::"); + Class ownerClass = Class.forName(parts[0]); + String methodName = parts[1]; + MethodHandle method = MethodHandles.publicLookup().findStatic(ownerClass, methodName, signature); + supplier = () -> + { + int value = 0; + try + { + value = (int) method.invoke(); + } + catch (Throwable ex) + { + LangUtil.rethrowUnchecked(ex); + } + + return value; + }; + } + catch (Throwable ex) + { + LangUtil.rethrowUnchecked(ex); + } + + return supplier; + } + + private static int defaultSubscriptionId() + { + int randomValue = Math.abs(new Random().nextInt()); + return randomValue | GENERATED_SUBSCRIPTION_ID_MASK; + } +} diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttReasonCodes.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttReasonCodes.java similarity index 91% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttReasonCodes.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttReasonCodes.java index fca1bfba29..a85589a5b5 100644 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttReasonCodes.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttReasonCodes.java @@ -21,9 +21,9 @@ public final class MqttReasonCodes public static final byte NORMAL_DISCONNECT = 0x00; - public static final byte GRANTED_QOS_1 = 0x00; - public static final byte GRANTED_QOS_2 = 0x01; - public static final byte GRANTED_QOS_3 = 0x02; + public static final byte GRANTED_QOS_0 = 0x00; + public static final byte GRANTED_QOS_1 = 0x01; + public static final byte GRANTED_QOS_2 = 0x02; public static final byte DISCONNECT_WITH_WILL_MESSAGE = 0x04; @@ -36,6 +36,7 @@ public final class MqttReasonCodes public static final byte UNSPECIFIED_ERROR = (byte) 0x80; public static final byte MALFORMED_PACKET = (byte) 0x81; public static final byte PROTOCOL_ERROR = (byte) 0x82; + public static final byte PACKET_TOO_LARGE = (byte) 0x95; public static final byte WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = (byte) 0xa2; public static final byte SHARED_SUBSCRIPTION_NOT_SUPPORTED = (byte) 0x9e; public static final byte SUBSCRIPTION_IDS_NOT_SUPPORTED = (byte) 0xa1; @@ -57,6 +58,7 @@ public final class MqttReasonCodes public static final byte TOPIC_NAME_INVALID = (byte) 0x90; public static final byte PAYLOAD_FORMAT_INVALID = (byte) 0x99; public static final byte QOS_NOT_SUPPORTED = (byte) 0x9b; + public static final byte SERVER_MOVED = (byte) 0x9d; public static final byte PACKET_IDENTIFIER_IN_USE = (byte) 0x91; public static final byte PACKET_IDENTIFIER_NOT_FOUND = (byte) 0x92; diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttValidator.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttValidator.java similarity index 100% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttValidator.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttValidator.java diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttAuthorizationConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttAuthorizationConfig.java new file mode 100644 index 0000000000..e4f19cc6a0 --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttAuthorizationConfig.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import java.util.List; + +public final class MqttAuthorizationConfig +{ + public final String name; + public final MqttCredentialsConfig credentials; + + public MqttAuthorizationConfig( + String name, + MqttCredentialsConfig credentials) + { + this.name = name; + this.credentials = credentials; + } + + public static final class MqttCredentialsConfig + { + public final List connect; + + public MqttCredentialsConfig( + List connect) + { + this.connect = connect; + } + } + + public enum MqttConnectProperty + { + USERNAME, + PASSWORD; + + public static MqttConnectProperty ofName( + String value) + { + MqttConnectProperty field = null; + switch (value) + { + case "username": + field = USERNAME; + break; + case "password": + field = PASSWORD; + break; + } + return field; + } + } + + public static final class MqttPatternConfig + { + public final MqttConnectProperty property; + public final String pattern; + + public MqttPatternConfig( + MqttConnectProperty property, + String pattern) + { + this.property = property; + this.pattern = pattern; + } + } +} + diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttBindingConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttBindingConfig.java new file mode 100644 index 0000000000..529623c069 --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttBindingConfig.java @@ -0,0 +1,145 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import static java.util.stream.Collectors.toList; + +import java.util.List; +import java.util.function.Function; +import java.util.function.ToLongFunction; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttConnectProperty; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttCredentialsConfig; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttPatternConfig; +import io.aklivity.zilla.runtime.engine.config.BindingConfig; +import io.aklivity.zilla.runtime.engine.config.KindConfig; + +public final class MqttBindingConfig +{ + private static final Function DEFAULT_CREDENTIALS = x -> null; + + public final long id; + public final String name; + public final KindConfig kind; + public final MqttOptionsConfig options; + public final List routes; + public final Function credentials; + public final ToLongFunction resolveId; + + public MqttBindingConfig( + BindingConfig binding) + { + this.id = binding.id; + this.name = binding.name; + this.kind = binding.kind; + this.routes = binding.routes.stream().map(MqttRouteConfig::new).collect(toList()); + this.options = (MqttOptionsConfig) binding.options; + this.resolveId = binding.resolveId; + this.credentials = options != null && options.authorization != null ? + asAccessor(options.authorization.credentials) : DEFAULT_CREDENTIALS; + } + + public MqttRouteConfig resolve( + long authorization) + { + return routes.stream() + .filter(r -> r.authorized(authorization)) + .findFirst() + .orElse(null); + } + + public MqttRouteConfig resolveSession( + long authorization, + String clientId) + { + return routes.stream() + .filter(r -> r.authorized(authorization) && r.matchesSession(clientId)) + .findFirst() + .orElse(null); + } + + public MqttRouteConfig resolveSubscribe( + long authorization, + String topic) + { + return routes.stream() + .filter(r -> r.authorized(authorization) && r.matchesSubscribe(topic)) + .findFirst() + .orElse(null); + } + + public MqttRouteConfig resolvePublish( + long authorization, + String topic) + { + return routes.stream() + .filter(r -> r.authorized(authorization) && r.matchesPublish(topic)) + .findFirst() + .orElse(null); + } + + public Function credentials() + { + return credentials; + } + + public MqttConnectProperty authField() + { + return options != null && options.authorization != null ? + options.authorization.credentials.connect.get(0).property : null; + } + + private Function asAccessor( + MqttCredentialsConfig credentials) + { + Function accessor = DEFAULT_CREDENTIALS; + List connectPatterns = credentials.connect; + + if (connectPatterns != null && !connectPatterns.isEmpty()) + { + MqttPatternConfig config = connectPatterns.get(0); + + Matcher connectMatch = + Pattern.compile(config.pattern.replace("{credentials}", "(?[^\\s]+)")) + .matcher(""); + + accessor = orElseIfNull(accessor, connect -> + { + String result = null; + if (connect != null && connectMatch.reset(connect).matches()) + { + result = connectMatch.group("credentials"); + } + return result; + }); + } + + return accessor; + } + + private static Function orElseIfNull( + Function first, + Function second) + { + return x -> + { + String result = first.apply(x); + return result != null ? result : second.apply(x); + }; + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapter.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapter.java new file mode 100644 index 0000000000..08eb3a7b94 --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapter.java @@ -0,0 +1,140 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.bind.adapter.JsonbAdapter; + +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttConditionConfig; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttConditionConfigBuilder; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttPublishConfig; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttSessionConfig; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttSubscribeConfig; +import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttBinding; +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; +import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; + +public final class MqttConditionConfigAdapter implements ConditionConfigAdapterSpi, JsonbAdapter +{ + private static final String SESSION_NAME = "session"; + private static final String SUBSCRIBE_NAME = "subscribe"; + private static final String PUBLISH_NAME = "publish"; + private static final String CLIENT_ID_NAME = "client-id"; + private static final String TOPIC_NAME = "topic"; + public static final String CLIENT_ID_DEFAULT = "*"; + + @Override + public String type() + { + return MqttBinding.NAME; + } + + @Override + public JsonObject adaptToJson( + ConditionConfig condition) + { + MqttConditionConfig mqttCondition = (MqttConditionConfig) condition; + + JsonObjectBuilder object = Json.createObjectBuilder(); + + if (!mqttCondition.sessions.isEmpty()) + { + JsonArrayBuilder sessions = Json.createArrayBuilder(); + + mqttCondition.sessions.forEach(p -> + { + JsonObjectBuilder sessionJson = Json.createObjectBuilder(); + sessionJson.add(CLIENT_ID_NAME, p.clientId); + sessions.add(sessionJson); + }); + object.add(SESSION_NAME, sessions); + } + + if (!mqttCondition.subscribes.isEmpty()) + { + JsonArrayBuilder subscribes = Json.createArrayBuilder(); + + mqttCondition.subscribes.forEach(s -> + { + JsonObjectBuilder subscribeJson = Json.createObjectBuilder(); + subscribeJson.add(TOPIC_NAME, s.topic); + subscribes.add(subscribeJson); + }); + object.add(SUBSCRIBE_NAME, subscribes); + } + + if (!mqttCondition.publishes.isEmpty()) + { + JsonArrayBuilder publishes = Json.createArrayBuilder(); + + mqttCondition.publishes.forEach(p -> + { + JsonObjectBuilder publishJson = Json.createObjectBuilder(); + publishJson.add(TOPIC_NAME, p.topic); + publishes.add(publishJson); + }); + object.add(PUBLISH_NAME, publishes); + } + + return object.build(); + } + + @Override + public ConditionConfig adaptFromJson( + JsonObject object) + { + MqttConditionConfigBuilder mqttConfig = MqttConditionConfig.builder(); + + if (object.containsKey(SESSION_NAME)) + { + JsonArray sessionsJson = object.getJsonArray(SESSION_NAME); + sessionsJson.forEach(s -> + { + String clientId = s.asJsonObject().getString(CLIENT_ID_NAME, CLIENT_ID_DEFAULT); + MqttSessionConfig session = new MqttSessionConfig(clientId); + mqttConfig.session(session); + }); + } + + if (object.containsKey(SUBSCRIBE_NAME)) + { + JsonArray subscribesJson = object.getJsonArray(SUBSCRIBE_NAME); + subscribesJson.forEach(s -> + { + String topic = s.asJsonObject().getString(TOPIC_NAME); + MqttSubscribeConfig subscribe = new MqttSubscribeConfig(topic); + mqttConfig.subscribe(subscribe); + }); + } + + if (object.containsKey(PUBLISH_NAME)) + { + JsonArray publishesJson = object.getJsonArray(PUBLISH_NAME); + publishesJson.forEach(p -> + { + String topic = p.asJsonObject().getString(TOPIC_NAME); + MqttPublishConfig publish = new MqttPublishConfig(topic); + mqttConfig.publish(publish); + }); + } + + return mqttConfig.build(); + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionMatcher.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionMatcher.java new file mode 100644 index 0000000000..eb98ea423a --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionMatcher.java @@ -0,0 +1,134 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttConditionConfig; + +public final class MqttConditionMatcher +{ + private final List sessionMatchers; + private final List subscribeMatchers; + private final List publishMatchers; + + public MqttConditionMatcher( + MqttConditionConfig condition) + { + this.sessionMatchers = + condition.sessions != null && !condition.sessions.isEmpty() ? + asWildcardMatcher(condition.sessions.stream().map(s -> s.clientId).collect(Collectors.toList())) : null; + this.subscribeMatchers = + condition.subscribes != null && !condition.subscribes.isEmpty() ? + asTopicMatcher(condition.subscribes.stream().map(s -> s.topic).collect(Collectors.toList())) : null; + this.publishMatchers = + condition.publishes != null && !condition.publishes.isEmpty() ? + asTopicMatcher(condition.publishes.stream().map(s -> s.topic).collect(Collectors.toList())) : null; + } + + public boolean matchesSession( + String clientId) + { + boolean match = sessionMatchers == null; + if (!match) + { + for (Matcher matcher : sessionMatchers) + { + match = matcher.reset(clientId).matches(); + if (match) + { + break; + } + } + } + return match; + } + + public boolean matchesSubscribe( + String topic) + { + boolean match = subscribeMatchers == null; + if (!match) + { + for (Matcher matcher : subscribeMatchers) + { + match = matcher.reset(topic).matches(); + if (match) + { + break; + } + } + } + return match; + } + + public boolean matchesPublish( + String topic) + { + boolean match = publishMatchers == null; + if (!match) + { + for (Matcher matcher : publishMatchers) + { + match = matcher.reset(topic).matches(); + if (match) + { + break; + } + } + } + return match; + } + + private static List asWildcardMatcher( + List wildcards) + { + List matchers = new ArrayList<>(); + for (String wildcard : wildcards) + { + String pattern = wildcard.replace(".", "\\.").replace("*", ".*"); + + if (!pattern.endsWith(".*")) + { + pattern = pattern + "(\\?.*)?"; + } + matchers.add(Pattern.compile(pattern).matcher("")); + + } + + return matchers; + } + + private static List asTopicMatcher( + List wildcards) + { + List matchers = new ArrayList<>(); + for (String wildcard : wildcards) + { + matchers.add(Pattern.compile(wildcard + .replace(".", "\\.") + .replace("$", "\\$") + .replace("+", "[^/]*") + .replace("#", ".*")).matcher("")); + + } + return matchers; + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfig.java new file mode 100644 index 0000000000..f3862661e7 --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfig.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public class MqttOptionsConfig extends OptionsConfig +{ + public final MqttAuthorizationConfig authorization; + + public MqttOptionsConfig( + MqttAuthorizationConfig authorization) + { + this.authorization = authorization; + } +} diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfigAdapter.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfigAdapter.java new file mode 100644 index 0000000000..d913fa7c3a --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfigAdapter.java @@ -0,0 +1,150 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.bind.adapter.JsonbAdapter; + +import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttBinding; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttCredentialsConfig; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttPatternConfig; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; + +public class MqttOptionsConfigAdapter implements OptionsConfigAdapterSpi, JsonbAdapter +{ + private static final String AUTHORIZATION_NAME = "authorization"; + private static final String AUTHORIZATION_CREDENTIALS_NAME = "credentials"; + private static final String AUTHORIZATION_CREDENTIALS_CONNECT_NAME = "connect"; + private static final String AUTHORIZATION_CREDENTIALS_USERNAME_NAME = "username"; + private static final String AUTHORIZATION_CREDENTIALS_PASSWORD_NAME = "password"; + + @Override + public Kind kind() + { + return Kind.BINDING; + } + + @Override + public String type() + { + return MqttBinding.NAME; + } + + @Override + public JsonObject adaptToJson( + OptionsConfig options) + { + MqttOptionsConfig mqttOptions = (MqttOptionsConfig) options; + + JsonObjectBuilder object = Json.createObjectBuilder(); + + MqttAuthorizationConfig mqttAuthorization = mqttOptions.authorization; + if (mqttAuthorization != null) + { + JsonObjectBuilder authorizations = Json.createObjectBuilder(); + + JsonObjectBuilder authorization = Json.createObjectBuilder(); + + MqttCredentialsConfig mqttCredentials = mqttAuthorization.credentials; + if (mqttCredentials != null) + { + JsonObjectBuilder credentials = Json.createObjectBuilder(); + + if (mqttCredentials.connect != null) + { + JsonObjectBuilder connect = Json.createObjectBuilder(); + + mqttCredentials.connect.forEach(p -> connect.add(p.property.name().toLowerCase(), p.pattern)); + + credentials.add(AUTHORIZATION_CREDENTIALS_CONNECT_NAME, connect); + } + + authorization.add(AUTHORIZATION_CREDENTIALS_NAME, credentials); + + authorizations.add(mqttAuthorization.name, authorization); + } + + object.add(AUTHORIZATION_NAME, authorizations); + } + + return object.build(); + } + + @Override + public OptionsConfig adaptFromJson( + JsonObject object) + { + MqttAuthorizationConfig newAuthorization = null; + + JsonObject authorizations = object.containsKey(AUTHORIZATION_NAME) + ? object.getJsonObject(AUTHORIZATION_NAME) + : null; + + if (authorizations != null) + { + for (String name : authorizations.keySet()) + { + JsonObject authorization = authorizations.getJsonObject(name); + + MqttCredentialsConfig newCredentials = null; + + JsonObject credentials = authorization.getJsonObject(AUTHORIZATION_CREDENTIALS_NAME); + + if (credentials != null) + { + List newConnect = + adaptPatternFromJson(credentials, AUTHORIZATION_CREDENTIALS_CONNECT_NAME); + + newCredentials = new MqttCredentialsConfig(newConnect); + } + + newAuthorization = new MqttAuthorizationConfig(name, newCredentials); + } + } + + return new MqttOptionsConfig(newAuthorization); + } + + private List adaptPatternFromJson( + JsonObject object, + String property) + { + List newPatterns = null; + if (object.containsKey(property)) + { + newPatterns = new ArrayList<>(); + + JsonObject patterns = object.getJsonObject(property); + for (String name : patterns.keySet()) + { + name = name.toLowerCase(); + if (name.equals(AUTHORIZATION_CREDENTIALS_USERNAME_NAME) || + name.equals(AUTHORIZATION_CREDENTIALS_PASSWORD_NAME)) + { + String pattern = patterns.getString(name); + newPatterns.add(new MqttPatternConfig(MqttAuthorizationConfig.MqttConnectProperty.ofName(name), pattern)); + } + } + } + return newPatterns; + } +} diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttRouteConfig.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttRouteConfig.java similarity index 79% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttRouteConfig.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttRouteConfig.java index 6e9c214e20..da76cf42d9 100644 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttRouteConfig.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttRouteConfig.java @@ -20,11 +20,10 @@ import java.util.List; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class MqttRouteConfig extends OptionsConfig +public final class MqttRouteConfig { public final long id; @@ -48,16 +47,21 @@ boolean authorized( return authorized.test(authorization); } - boolean matches( - MqttCapabilities capabilities) + boolean matchesSession( + String clientId) { - return when.isEmpty() || when.stream().anyMatch(m -> m.matches(capabilities)); + return when.isEmpty() || when.stream().anyMatch(m -> m.matchesSession(clientId)); } - boolean matches( - String topic, - MqttCapabilities capabilities) + boolean matchesSubscribe( + String topic) { - return when.isEmpty() || when.stream().anyMatch(m -> m.matches(topic, capabilities)); + return when.isEmpty() || when.stream().anyMatch(m -> m.matchesSubscribe(topic)); + } + + boolean matchesPublish( + String topic) + { + return when.isEmpty() || when.stream().anyMatch(m -> m.matchesPublish(topic)); } } diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java new file mode 100644 index 0000000000..cdbeb1a378 --- /dev/null +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java @@ -0,0 +1,4176 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.GENERATED_SUBSCRIPTION_ID_MASK; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.BAD_AUTHENTICATION_METHOD; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.MALFORMED_PACKET; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.NORMAL_DISCONNECT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.PACKET_TOO_LARGE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.PAYLOAD_FORMAT_INVALID; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.PROTOCOL_ERROR; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.QOS_NOT_SUPPORTED; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.RETAIN_NOT_SUPPORTED; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.SUCCESS; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.TOPIC_ALIAS_INVALID; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttPublishFlags.RETAIN; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttSubscribeFlags.NO_LOCAL; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttSubscribeFlags.RETAIN_AS_PUBLISHED; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttSubscribeFlags.SEND_RETAINED; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_ASSIGNED_CLIENT_ID; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_AUTHENTICATION_DATA; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_AUTHENTICATION_METHOD; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_CONTENT_TYPE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_CORRELATION_DATA; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_EXPIRY_INTERVAL; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_MAXIMUM_PACKET_SIZE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_MAXIMUM_QO_S; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_PAYLOAD_FORMAT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_RECEIVE_MAXIMUM; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_RESPONSE_TOPIC; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_RETAIN_AVAILABLE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_SERVER_KEEP_ALIVE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_SESSION_EXPIRY; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_SHARED_SUBSCRIPTION_AVAILABLE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_SUBSCRIPTION_ID; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_SUBSCRIPTION_IDS_AVAILABLE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_TOPIC_ALIAS; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_TOPIC_ALIAS_MAXIMUM; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_USER_PROPERTY; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW.KIND_WILDCARD_SUBSCRIPTION_AVAILABLE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.DataFW.FIELD_OFFSET_PAYLOAD; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttPublishDataExFW.Builder.DEFAULT_EXPIRY_INTERVAL; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttPublishDataExFW.Builder.DEFAULT_FORMAT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttServerCapabilities.SHARED_SUBSCRIPTIONS; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttServerCapabilities.SUBSCRIPTION_IDS; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttServerCapabilities.WILDCARD; +import static io.aklivity.zilla.runtime.engine.budget.BudgetCreditor.NO_CREDITOR_INDEX; +import static io.aklivity.zilla.runtime.engine.budget.BudgetDebitor.NO_DEBITOR_INDEX; +import static io.aklivity.zilla.runtime.engine.buffer.BufferPool.NO_SLOT; +import static io.aklivity.zilla.runtime.engine.concurrent.Signaler.NO_CANCEL_ID; +import static java.nio.ByteOrder.BIG_ENDIAN; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.function.LongFunction; +import java.util.function.LongSupplier; +import java.util.function.LongUnaryOperator; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.agrona.DirectBuffer; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.Int2ObjectHashMap; +import org.agrona.collections.Long2ObjectHashMap; +import org.agrona.collections.ObjectHashSet; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttBinding; +import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttBindingConfig; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttRouteConfig; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.Array32FW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.Flyweight; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttBinaryFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttPayloadFormat; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttPayloadFormatFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttQoS; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttSessionFlags; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttSessionStateFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttTopicFilterFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttWillMessageFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.OctetsFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.String16FW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.Varuint32FW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttConnackFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttConnectFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttDisconnectFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPacketHeaderFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPacketType; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPingReqFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPingRespFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertiesFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPropertyFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttPublishFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttSubackFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttSubackPayloadFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttSubscribeFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttSubscribePayloadFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttUnsubackFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttUnsubackPayloadFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttUnsubscribeFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttUnsubscribePayloadFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttUserPropertyFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.codec.MqttWillFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.AbortFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.BeginFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.DataFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.EndFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.ExtensionFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.FlushFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttPublishBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttPublishDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttResetExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttSessionBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttSessionDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttSubscribeBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttSubscribeFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.ResetFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.SignalFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.WindowFW; +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.binding.BindingHandler; +import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; +import io.aklivity.zilla.runtime.engine.budget.BudgetCreditor; +import io.aklivity.zilla.runtime.engine.budget.BudgetDebitor; +import io.aklivity.zilla.runtime.engine.buffer.BufferPool; +import io.aklivity.zilla.runtime.engine.concurrent.Signaler; +import io.aklivity.zilla.runtime.engine.config.BindingConfig; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttServerCapabilities; + +public final class MqttClientFactory implements MqttStreamFactory +{ + private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(new UnsafeBuffer(new byte[0]), 0, 0); + + private static final String16FW MQTT_PROTOCOL_NAME = new String16FW("MQTT", BIG_ENDIAN); + private static final int MQTT_PROTOCOL_VERSION = 5; + private static final int CONNACK_FIXED_HEADER = 0b0010_0000; + private static final int SUBACK_FIXED_HEADER = 0b1001_0000; + private static final int UNSUBACK_FIXED_HEADER = 0b1011_0000; + private static final int DISCONNECT_FIXED_HEADER = 0b1110_0000; + + private static final int NO_FLAGS = 0b0000_0000; + private static final int RETAIN_MASK = 0b0000_0001; + private static final int PUBLISH_QOS1_MASK = 0b0000_0010; + private static final int PUBLISH_QOS2_MASK = 0b0000_0100; + private static final int NO_LOCAL_FLAG_MASK = 0b0000_0100; + private static final int RETAIN_AS_PUBLISHED_MASK = 0b0000_1000; + private static final int RETAIN_HANDLING_MASK = 0b0011_0000; + + private static final int WILL_FLAG_MASK = 0b0000_0100; + private static final int WILL_QOS_MASK = 0b0001_1000; + private static final int WILL_RETAIN_MASK = 0b0010_0000; + + private static final int CONNACK_SESSION_PRESENT_MASK = 0b0000_0001; + private static final int CONNACK_RESERVED_FLAGS_MASK = 0b1111_1110; + + private static final int CONNACK_SESSION_EXPIRY_MASK = 0b0000_0000_0001; + private static final int CONNACK_MAXIMUM_QOS_MASK = 0b0000_0000_0010; + private static final int CONNACK_RETAIN_AVAILABLE_MASK = 0b0000_0000_0100; + private static final int CONNACK_MAXIMUM_PACKET_SIZE_MASK = 0b0000_0000_1000; + private static final int CONNACK_ASSIGNED_CLIENT_IDENTIFIER_MASK = 0b0000_0001_0000; + private static final int CONNACK_WILDCARD_SUBSCRIPTION_AVAILABLE_MASK = 0b0000_0010_0000; + private static final int CONNACK_SUBSCRIPTION_IDENTIFIERS_MASK = 0b0000_0100_0000; + private static final int CONNACK_SHARED_SUBSCRIPTION_AVAILABLE_MASK = 0b0000_1000_0000; + private static final int CONNACK_KEEP_ALIVE_MASK = 0b0001_0000_0000; + private static final int CONNACK_TOPIC_ALIAS_MAXIMUM_MASK = 0b0010_0000_0000; + + private static final int SHARED_SUBSCRIPTION_AVAILABLE_MASK = 1 << SHARED_SUBSCRIPTIONS.value(); + private static final int WILDCARD_AVAILABLE_MASK = 1 << WILDCARD.value(); + private static final int SUBSCRIPTION_IDS_AVAILABLE_MASK = 1 << SUBSCRIPTION_IDS.value(); + private static final int RETAIN_AVAILABLE_MASK = 1 << RETAIN.value(); + + private static final int RETAIN_FLAG = 1 << RETAIN.ordinal(); + private static final int SEND_RETAINED_FLAG = 1 << SEND_RETAINED.ordinal(); + private static final int RETAIN_AS_PUBLISHED_FLAG = 1 << RETAIN_AS_PUBLISHED.ordinal(); + private static final int NO_LOCAL_FLAG = 1 << NO_LOCAL.ordinal(); + private static final int DO_NOT_SEND_RETAINED_MASK = 0b0010_0000; + + private static final int PUBLISH_TYPE = 0x03; + + private static final int PUBLISH_EXPIRED_SIGNAL = 1; + private static final int KEEP_ALIVE_TIMEOUT_SIGNAL = 2; + private static final int CONNACK_TIMEOUT_SIGNAL = 3; + private static final int PINGRESP_TIMEOUT_SIGNAL = 4; + + private static final int PUBLISH_FRAMING = 255; + private static final int KEEP_ALIVE = 60000; + + private static final String16FW NULL_STRING = new String16FW((String) null); + public static final String SHARED_SUBSCRIPTION_LITERAL = "$share"; + + + private final BeginFW beginRO = new BeginFW(); + private final FlushFW flushRO = new FlushFW(); + private final DataFW dataRO = new DataFW(); + private final EndFW endRO = new EndFW(); + private final AbortFW abortRO = new AbortFW(); + private final WindowFW windowRO = new WindowFW(); + private final ResetFW resetRO = new ResetFW(); + private final SignalFW signalRO = new SignalFW(); + + private final BeginFW.Builder beginRW = new BeginFW.Builder(); + private final DataFW.Builder dataRW = new DataFW.Builder(); + private final EndFW.Builder endRW = new EndFW.Builder(); + private final AbortFW.Builder abortRW = new AbortFW.Builder(); + private final WindowFW.Builder windowRW = new WindowFW.Builder(); + private final ResetFW.Builder resetRW = new ResetFW.Builder(); + private final FlushFW.Builder flushRW = new FlushFW.Builder(); + + private final ExtensionFW extensionRO = new ExtensionFW(); + private final MqttDataExFW mqttPublishDataExRO = new MqttDataExFW(); + private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); + private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); + private final MqttFlushExFW mqttFlushExRO = new MqttFlushExFW(); + + private final MqttBeginExFW.Builder mqttSessionBeginExRW = new MqttBeginExFW.Builder(); + private final MqttDataExFW.Builder mqttPublishDataExRW = new MqttDataExFW.Builder(); + private final MqttResetExFW.Builder mqttResetExRW = new MqttResetExFW.Builder(); + private final MqttWillFW.Builder willMessageRW = new MqttWillFW.Builder(); + private final MqttPacketHeaderFW mqttPacketHeaderRO = new MqttPacketHeaderFW(); + private final MqttConnackFW mqttConnackRO = new MqttConnackFW(); + private final MqttSubackFW mqttSubackRO = new MqttSubackFW(); + private final MqttUnsubackFW mqttUnsubackRO = new MqttUnsubackFW(); + private final MqttWillFW mqttWillRO = new MqttWillFW(); + private final MqttWillMessageFW mqttWillMessageRO = new MqttWillMessageFW(); + private final MqttPublishFW mqttPublishRO = new MqttPublishFW(); + private final MqttSubackPayloadFW mqttSubackPayloadRO = new MqttSubackPayloadFW(); + private final MqttUnsubackPayloadFW mqttUnsubackPayloadRO = new MqttUnsubackPayloadFW(); + private final MqttSubscribePayloadFW.Builder mqttSubscribePayloadRW = new MqttSubscribePayloadFW.Builder(); + private final MqttUnsubscribePayloadFW.Builder mqttUnsubscribePayloadRW = new MqttUnsubscribePayloadFW.Builder(); + private final MqttPingRespFW mqttPingRespRO = new MqttPingRespFW(); + private final MqttDisconnectFW mqttDisconnectRO = new MqttDisconnectFW(); + + private final OctetsFW octetsRO = new OctetsFW(); + private final OctetsFW.Builder octetsRW = new OctetsFW.Builder(); + + private final MqttPropertyFW mqttPropertyRO = new MqttPropertyFW(); + private final MqttPropertyFW.Builder mqttPropertyRW = new MqttPropertyFW.Builder(); + private final MqttPropertyFW.Builder mqttWillPropertyRW = new MqttPropertyFW.Builder(); + private final MqttSessionStateFW.Builder mqttSessionStateRW = new MqttSessionStateFW.Builder(); + + private final MqttSessionStateFW mqttSessionStateRO = new MqttSessionStateFW(); + + private final String16FW contentTypeRO = new String16FW(BIG_ENDIAN); + private final String16FW responseTopicRO = new String16FW(BIG_ENDIAN); + + private final MqttPublishHeader mqttPublishHeaderRO = new MqttPublishHeader(); + + private final MqttConnectFW.Builder mqttConnectRW = new MqttConnectFW.Builder(); + private final MqttSubscribeFW.Builder mqttSubscribeRW = new MqttSubscribeFW.Builder(); + private final MqttUnsubscribeFW.Builder mqttUnsubscribeRW = new MqttUnsubscribeFW.Builder(); + private final MqttPublishFW.Builder mqttPublishRW = new MqttPublishFW.Builder(); + private final MqttPingReqFW.Builder mqttPingReqRW = new MqttPingReqFW.Builder(); + private final MqttDisconnectFW.Builder mqttDisconnectRW = new MqttDisconnectFW.Builder(); + private final Array32FW.Builder userPropertiesRW = + new Array32FW.Builder<>(new MqttUserPropertyFW.Builder(), new MqttUserPropertyFW()); + private final Array32FW.Builder subscriptionIdsRW = + new Array32FW.Builder<>(new Varuint32FW.Builder(), new Varuint32FW()); + private final MqttClientDecoder decodeInitialType = this::decodeInitialType; + private final MqttClientDecoder decodePacketType = this::decodePacketType; + private final MqttClientDecoder decodeConnack = this::decodeConnack; + private final MqttClientDecoder decodeSuback = this::decodeSuback; + private final MqttClientDecoder decodeUnsuback = this::decodeUnsuback; + private final MqttClientDecoder decodePublish = this::decodePublish; + private final MqttClientDecoder decodePingresp = this::decodePingResp; + private final MqttClientDecoder decodeDisconnect = this::decodeDisconnect; + private final MqttClientDecoder decodeIgnoreAll = this::decodeIgnoreAll; + private final MqttClientDecoder decodeUnknownType = this::decodeUnknownType; + + private final Map decodersByPacketType; + private final Long2ObjectHashMap clients; + + private int maximumPacketSize; + + { + final Map decodersByPacketType = new EnumMap<>(MqttPacketType.class); + decodersByPacketType.put(MqttPacketType.CONNACK, decodeConnack); + decodersByPacketType.put(MqttPacketType.SUBACK, decodeSuback); + decodersByPacketType.put(MqttPacketType.UNSUBACK, decodeUnsuback); + decodersByPacketType.put(MqttPacketType.PUBLISH, decodePublish); + // decodersByPacketType.put(MqttPacketType.PUBREC, decodePubrec); + // decodersByPacketType.put(MqttPacketType.PUBREL, decodePubrel); + // decodersByPacketType.put(MqttPacketType.PUBCOMP, decodePubcomp); + decodersByPacketType.put(MqttPacketType.PINGRESP, decodePingresp); + decodersByPacketType.put(MqttPacketType.DISCONNECT, decodeDisconnect); + // decodersByPacketType.put(MqttPacketType.AUTH, decodeAuth); + this.decodersByPacketType = decodersByPacketType; + } + + private final MutableDirectBuffer writeBuffer; + private final MutableDirectBuffer extBuffer; + private final MutableDirectBuffer dataExtBuffer; + private final MutableDirectBuffer sessionStateBuffer; + private final MutableDirectBuffer payloadBuffer; + private final MutableDirectBuffer propertyBuffer; + private final MutableDirectBuffer userPropertiesBuffer; + private final MutableDirectBuffer subscriptionIdsBuffer; + private final MutableDirectBuffer willMessageBuffer; + private final MutableDirectBuffer willPropertyBuffer; + + private final ByteBuffer charsetBuffer; + private final BufferPool bufferPool; + private final BudgetCreditor creditor; + private final Signaler signaler; + private final MessageConsumer droppedHandler; + private final BindingHandler streamFactory; + private final LongUnaryOperator supplyInitialId; + private final LongUnaryOperator supplyReplyId; + private final LongSupplier supplyTraceId; + private final LongSupplier supplyBudgetId; + private final LongFunction supplyDebitor; + private final Long2ObjectHashMap bindings; + private final int mqttTypeId; + + private final long publishTimeoutMillis; + private final long connackTimeoutMillis; + private final int encodeBudgetMax; + + private final CharsetDecoder utf8Decoder; + + public MqttClientFactory( + MqttConfiguration config, + EngineContext context) + { + this.writeBuffer = context.writeBuffer(); + this.extBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.dataExtBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.sessionStateBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.propertyBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.userPropertiesBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.subscriptionIdsBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.payloadBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.charsetBuffer = ByteBuffer.wrap(new byte[writeBuffer.capacity()]); + this.willMessageBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.willPropertyBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.bufferPool = context.bufferPool(); + this.creditor = context.creditor(); + this.signaler = context.signaler(); + this.droppedHandler = context.droppedFrameHandler(); + this.streamFactory = context.streamFactory(); + this.supplyDebitor = context::supplyDebitor; + this.supplyInitialId = context::supplyInitialId; + this.supplyReplyId = context::supplyReplyId; + this.supplyBudgetId = context::supplyBudgetId; + this.supplyTraceId = context::supplyTraceId; + this.bindings = new Long2ObjectHashMap<>(); + this.mqttTypeId = context.supplyTypeId(MqttBinding.NAME); + this.publishTimeoutMillis = SECONDS.toMillis(config.publishTimeout()); + this.connackTimeoutMillis = SECONDS.toMillis(config.connackTimeout()); + this.maximumPacketSize = writeBuffer.capacity(); + this.encodeBudgetMax = bufferPool.slotCapacity(); + this.utf8Decoder = StandardCharsets.UTF_8.newDecoder(); + this.clients = new Long2ObjectHashMap<>(); + } + + @Override + public void attach( + BindingConfig binding) + { + MqttBindingConfig mqttBinding = new MqttBindingConfig(binding); + bindings.put(binding.id, mqttBinding); + } + + @Override + public void detach( + long bindingId) + { + bindings.remove(bindingId); + } + + @Override + public MessageConsumer newStream( + int msgTypeId, + DirectBuffer buffer, + int index, + int length, + MessageConsumer sender) + { + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + final long originId = begin.originId(); + final long routedId = begin.routedId(); + final long initialId = begin.streamId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + MqttBindingConfig binding = bindings.get(routedId); + + final MqttRouteConfig resolved = binding != null ? binding.resolve(authorization) : null; + + MessageConsumer newStream = null; + + if (resolved != null) + { + final long resolvedId = resolved.id; + + final OctetsFW extension = begin.extension(); + final ExtensionFW beginEx = extension.get(extensionRO::tryWrap); + assert beginEx != null; + final int typeId = beginEx.typeId(); + assert typeId == mqttTypeId; + + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + final int kind = mqttBeginEx.kind(); + + MqttClient client = resolveClient(routedId, resolvedId, supplyInitialId.applyAsLong(resolvedId), affinity, kind); + switch (kind) + { + case MqttBeginExFW.KIND_SESSION: + client.sessionStream = new MqttSessionStream(client, sender, originId, routedId, initialId); + newStream = client.sessionStream::onSession; + break; + case MqttBeginExFW.KIND_PUBLISH: + MqttPublishStream publishStream = new MqttPublishStream(client, sender, originId, routedId, initialId); + newStream = publishStream::onPublish; + break; + case MqttBeginExFW.KIND_SUBSCRIBE: + MqttSubscribeStream subscribeStream = new MqttSubscribeStream(client, sender, originId, routedId, initialId); + newStream = subscribeStream::onSubscribe; + break; + } + } + + return newStream; + } + + private MqttClient resolveClient( + long routedId, + long resolvedId, + long initialId, + long affinity, + int kind) + { + return kind == MqttBeginExFW.KIND_SESSION ? clients.computeIfAbsent(affinity, + s -> new MqttClient(routedId, resolvedId, initialId, maximumPacketSize)) : clients.get(affinity); + } + + private MessageConsumer newStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private void doBegin( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + } + + private void doData( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int index, + int length, + Flyweight extension) + { + final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .payload(buffer, index, length) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + + private void doEnd( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Flyweight extension) + { + final EndFW end = endRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(end.typeId(), end.buffer(), end.offset(), end.sizeof()); + } + + private void doAbort( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Flyweight extension) + { + final AbortFW abort = abortRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(abort.typeId(), abort.buffer(), abort.offset(), abort.sizeof()); + } + + private void doWindow( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int padding) + { + final WindowFW window = windowRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .padding(padding) + .build(); + + receiver.accept(window.typeId(), window.buffer(), window.offset(), window.sizeof()); + } + + private void doReset( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + Flyweight extension) + { + final ResetFW reset = resetRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .extension(extension.buffer(), extension.offset(), extension.sizeof()) + .build(); + + receiver.accept(reset.typeId(), reset.buffer(), reset.offset(), reset.sizeof()); + } + + private void doFlush( + MessageConsumer receiver, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long budgetId, + int reserved, + Consumer extension) + { + final FlushFW flush = flushRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .budgetId(budgetId) + .reserved(reserved) + .extension(extension) + .build(); + + receiver.accept(flush.typeId(), flush.buffer(), flush.offset(), flush.sizeof()); + } + + private int decodeInitialType( + MqttClient client, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final MqttPacketHeaderFW packet = mqttPacketHeaderRO.tryWrap(buffer, offset, limit); + + decode: + if (packet != null) + { + final int length = packet.remainingLength(); + final MqttPacketType packetType = MqttPacketType.valueOf(packet.typeAndFlags() >> 4); + + if (packetType != MqttPacketType.CONNACK) + { + client.doNetworkEnd(traceId, authorization); + client.decoder = decodeIgnoreAll; + break decode; + } + + client.decodeablePacketBytes = packet.sizeof() + length; + client.decoder = decodePacketType; + } + + return offset; + } + + private int decodePacketType( + MqttClient server, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final MqttPacketHeaderFW packet = mqttPacketHeaderRO.tryWrap(buffer, offset, limit); + + if (packet != null) + { + final int length = packet.remainingLength(); + final MqttPacketType packetType = MqttPacketType.valueOf(packet.typeAndFlags() >> 4); + final MqttClientDecoder decoder = decodersByPacketType.getOrDefault(packetType, decodeUnknownType); + + if (packet.sizeof() + length > maximumPacketSize) + { + server.onDecodeError(traceId, authorization, PACKET_TOO_LARGE); + server.decoder = decodeIgnoreAll; + } + else if (limit - packet.limit() >= length) + { + server.decodeablePacketBytes = packet.sizeof() + length; + server.decoder = decoder; + } + } + + return offset; + } + + private int decodeConnack( + MqttClient client, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final int length = limit - offset; + + int progress = offset; + + if (length > 0) + { + int reasonCode = SUCCESS; + + final MqttConnackFW connack = mqttConnackRO.tryWrap(buffer, offset, limit); + int flags = 0; + decode: + { + if (connack == null) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + + else if ((connack.typeAndFlags() & 0b1111_1111) != CONNACK_FIXED_HEADER) + { + reasonCode = MALFORMED_PACKET; + break decode; + } + + flags = connack.flags(); + + reasonCode = decodeConnackFlags(flags); + if (reasonCode != SUCCESS) + { + break decode; + } + + progress = client.onDecodeConnack(traceId, authorization, buffer, progress, limit, connack); + client.decoder = decodePacketType; + } + + if (reasonCode != SUCCESS) + { + client.onDecodeError(traceId, authorization, reasonCode); + client.decoder = decodeIgnoreAll; + } + } + + return progress; + } + + private int decodeSuback( + MqttClient client, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final int length = limit - offset; + + int progress = offset; + + if (length > 0) + { + int reasonCode = SUCCESS; + + final MqttSubackFW suback = mqttSubackRO.tryWrap(buffer, offset, limit); + decode: + { + if (suback == null) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + else if ((suback.typeAndFlags() & 0b1111_1111) != SUBACK_FIXED_HEADER) + { + reasonCode = MALFORMED_PACKET; + break decode; + } + + progress = client.onDecodeSuback(traceId, authorization, buffer, progress, limit, suback); + client.decoder = decodePacketType; + } + + if (reasonCode != SUCCESS) + { + client.onDecodeError(traceId, authorization, reasonCode); + client.decoder = decodeIgnoreAll; + } + } + + return progress; + } + + private int decodeUnsuback( + MqttClient client, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final int length = limit - offset; + + int progress = offset; + + if (length > 0) + { + int reasonCode = SUCCESS; + + final MqttUnsubackFW unsuback = mqttUnsubackRO.tryWrap(buffer, offset, limit); + decode: + { + if (unsuback == null) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + else if ((unsuback.typeAndFlags() & 0b1111_1111) != UNSUBACK_FIXED_HEADER) + { + reasonCode = MALFORMED_PACKET; + break decode; + } + + progress = client.onDecodeUnsuback(traceId, authorization, buffer, progress, limit, unsuback); + client.decoder = decodePacketType; + } + + if (reasonCode != SUCCESS) + { + client.onDecodeError(traceId, authorization, reasonCode); + client.decoder = decodeIgnoreAll; + } + } + + return progress; + } + + private int decodePublish( + MqttClient client, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final int length = limit - offset; + + int progress = offset; + + decode: + if (length >= client.decodeablePacketBytes) + { + int reasonCode = SUCCESS; + final MqttPublishFW publish = mqttPublishRO.tryWrap(buffer, offset, offset + client.decodeablePacketBytes); + + final MqttPublishHeader mqttPublishHeader = mqttPublishHeaderRO.reset(); + + if (publish == null) + { + reasonCode = PROTOCOL_ERROR; + } + else + { + reasonCode = mqttPublishHeader.decode(client, publish.topicName(), publish.properties(), publish.typeAndFlags()); + } + + if (reasonCode == SUCCESS) + { + final int qos = mqttPublishHeader.qos; + MqttSubscribeStream subscriber = client.subscribeStreams.get(qos); + + + final Varuint32FW firstSubscriptionId = subscriptionIdsRW.build().matchFirst(s -> true); + final int subscriptionId = firstSubscriptionId != null ? firstSubscriptionId.value() : 0; + + boolean existSubscribeStream = subscriptionId != 0 ? client.existStreamForId(subscriptionId) + : client.existStreamForTopic(mqttPublishHeader.topic); + + if (!existSubscribeStream) + { + MqttSessionStateFW.Builder sessionStateBuilder = + mqttSessionStateRW.wrap(sessionStateBuffer, 0, sessionStateBuffer.capacity()); + client.sessionStream.subscriptions.forEach(s -> + sessionStateBuilder.subscriptionsItem(si -> + si.subscriptionId(s.id) + .qos(s.qos) + .flags(s.flags) + .pattern(s.filter))); + final Subscription adminSubscription = new Subscription(); + adminSubscription.id = subscriptionId; + adminSubscription.qos = mqttPublishHeader.qos; + adminSubscription.filter = mqttPublishHeader.topic; + client.sessionStream.subscriptions.add(adminSubscription); + + sessionStateBuilder.subscriptionsItem(si -> + si.subscriptionId(adminSubscription.id) + .qos(adminSubscription.qos) + .pattern(adminSubscription.filter)); + + MqttSessionStateFW sessionState = sessionStateBuilder.build(); + client.sessionStream.doSessionData(traceId, authorization, sessionState.sizeof(), EMPTY_OCTETS, sessionState); + + break decode; + } + + if (subscriber == null) + { + break decode; + } + + final OctetsFW payload = publish.payload(); + final int payloadSize = payload.sizeof(); + + if (mqttPublishHeaderRO.payloadFormat.equals(MqttPayloadFormat.TEXT) && invalidUtf8(payload)) + { + reasonCode = PAYLOAD_FORMAT_INVALID; + client.onDecodeError(traceId, authorization, reasonCode); + client.decoder = decodeIgnoreAll; + } + + boolean canPublish = MqttState.replyOpened(subscriber.state); + + int reserved = payloadSize + subscriber.replyPad; + canPublish &= subscriber.replySeq + reserved <= subscriber.replyAck + subscriber.replyMax; + + if (canPublish && subscriber.debitorIndex != NO_DEBITOR_INDEX && reserved != 0) + { + final int minimum = reserved; // TODO: fragmentation + reserved = subscriber.debitor.claim(subscriber.debitorIndex, subscriber.replyId, minimum, reserved); + } + + if (canPublish && (reserved != 0 || payloadSize == 0)) + { + client.onDecodePublish(traceId, authorization, reserved, payload, subscriber); + client.decodeablePacketBytes = 0; + client.decoder = decodePacketType; + progress = publish.limit(); + } + } + else + { + client.onDecodeError(traceId, authorization, reasonCode); + client.decoder = decodeIgnoreAll; + } + } + + return progress; + } + + private boolean invalidUtf8( + OctetsFW payload) + { + boolean invalid = false; + byte[] payloadBytes = charsetBuffer.array(); + final int payloadSize = payload.sizeof(); + payload.value().getBytes(0, payloadBytes, 0, payloadSize); + try + { + charsetBuffer.position(0).limit(payloadSize); + utf8Decoder.decode(charsetBuffer); + } + catch (CharacterCodingException ex) + { + invalid = true; + utf8Decoder.reset(); + } + return invalid; + } + + private int decodePingResp( + MqttClient client, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final int length = limit - offset; + + int progress = offset; + + if (length > 0) + { + final MqttPingRespFW ping = mqttPingRespRO.tryWrap(buffer, offset, limit); + if (ping == null) + { + client.onDecodeError(traceId, authorization, PROTOCOL_ERROR); + client.decoder = decodeIgnoreAll; + } + else + { + client.onDecodePingResp(traceId, authorization, ping); + client.decoder = decodePacketType; + progress = ping.limit(); + } + } + + return progress; + } + + private int decodeDisconnect( + MqttClient server, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + final int length = limit - offset; + + int progress = offset; + + if (length > 0) + { + int reasonCode = NORMAL_DISCONNECT; + + final MqttDisconnectFW disconnect = mqttDisconnectRO.tryWrap(buffer, offset, limit); + if (disconnect == null) + { + reasonCode = PROTOCOL_ERROR; + } + else if ((disconnect.typeAndFlags() & 0b1111_1111) != DISCONNECT_FIXED_HEADER) + { + reasonCode = MALFORMED_PACKET; + } + + if (reasonCode == 0) + { + server.onDecodeDisconnect(traceId, authorization, disconnect); + server.decoder = decodePacketType; + progress = disconnect.limit(); + } + else + { + server.onDecodeError(traceId, authorization, reasonCode); + server.decoder = decodeIgnoreAll; + } + } + + return progress; + } + + private int decodeIgnoreAll( + MqttClient server, + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + return limit; + } + + private int decodeUnknownType( + MqttClient server, + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + server.onDecodeError(traceId, authorization, PROTOCOL_ERROR); + server.decoder = decodeIgnoreAll; + return limit; + } + + @FunctionalInterface + private interface MqttClientDecoder + { + int decode( + MqttClient client, + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit); + } + + private final class MqttClient + { + private final AtomicInteger packetIdCounter; + private final long originId; + private final long routedId; + private final long replyId; + private final long initialId; + private final ObjectHashSet publishStreams; + private final Int2ObjectHashMap subscribeStreams; + private final Int2ObjectHashMap topicAliases; + private final long encodeBudgetId; + + private long budgetId; + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + private int initialPad; + + private MessageConsumer network; + private MqttSessionStream sessionStream; + + private long decodeSeq; + private long decodeAck; + private int decodeMax; + + private long encodeSeq; + private long encodeAck; + private int encodeMax; + private int encodePad; + + private long encodeBudgetIndex = NO_CREDITOR_INDEX; + private int encodeSharedBudget; + + private int decodeSlot = NO_SLOT; + private int decodeSlotOffset; + private int decodeSlotReserved; + + private int encodeSlot = NO_SLOT; + private int encodeSlotOffset; + private long encodeSlotTraceId; + + private MqttClientDecoder decoder; + private int decodeablePacketBytes; + + private long connackTimeoutId = NO_CANCEL_ID; + private long pingRespTimeoutId = NO_CANCEL_ID; + private long connackTimeoutAt; + private long pingRespTimeoutAt; + + private long keepAliveTimeoutId = NO_CANCEL_ID; + private long keepAliveTimeoutAt; + + private long keepAliveMillis = KEEP_ALIVE; + private long pingRespTimeoutMillis = (long) (KEEP_ALIVE * 0.5); + + private boolean connectAcked; + private short topicAliasMaximum = Short.MAX_VALUE; + private int flags = 0; + + private int capabilities = SHARED_SUBSCRIPTION_AVAILABLE_MASK | WILDCARD_AVAILABLE_MASK | + SUBSCRIPTION_IDS_AVAILABLE_MASK | RETAIN_AVAILABLE_MASK; + private int sessionExpiry = 0; + private String clientId; + private byte maximumQos = 2; + private int maximumPacketSize; + + private int decodablePropertyMask = 0; + + private MqttClient( + long originId, + long routedId, + long initialId, + int maximumPacketSize) + { + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.encodeBudgetId = supplyBudgetId.getAsLong(); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.decoder = decodeInitialType; + this.publishStreams = new ObjectHashSet<>(); + this.subscribeStreams = new Int2ObjectHashMap<>(); + this.topicAliases = new Int2ObjectHashMap<>(); + this.maximumPacketSize = maximumPacketSize; + this.packetIdCounter = new AtomicInteger(); + } + + private void onNetwork( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onNetworkBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onNetworkData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onNetworkEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onNetworkAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onNetworkWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onNetworkReset(reset); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onNetworkSignal(signal); + break; + default: + break; + } + } + + private void onNetworkBegin( + BeginFW begin) + { + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + + state = MqttState.openingInitial(state); + + assert encodeBudgetIndex == NO_CREDITOR_INDEX; + this.encodeBudgetIndex = creditor.acquire(encodeBudgetId); + + doNetworkWindow(traceId, authorization, 0, 0L, 0, bufferPool.slotCapacity()); + } + + private void onNetworkData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + + assert acknowledge <= sequence; + assert sequence >= decodeSeq; + assert acknowledge <= decodeAck; + + decodeSeq = sequence + data.reserved(); + + assert decodeAck <= decodeSeq; + + if (decodeSeq > decodeAck + decodeMax) + { + doNetworkReset(supplyTraceId.getAsLong(), authorization); + } + else + { + final long budgetId = data.budgetId(); + final OctetsFW payload = data.payload(); + + DirectBuffer buffer = payload.buffer(); + int offset = payload.offset(); + int limit = payload.limit(); + int reserved = data.reserved(); + + if (decodeSlot != NO_SLOT) + { + final MutableDirectBuffer slotBuffer = bufferPool.buffer(decodeSlot); + slotBuffer.putBytes(decodeSlotOffset, buffer, offset, limit - offset); + decodeSlotOffset += limit - offset; + decodeSlotReserved += reserved; + + buffer = slotBuffer; + offset = 0; + limit = decodeSlotOffset; + reserved = decodeSlotReserved; + } + + decodeNetwork(traceId, authorization, budgetId, reserved, buffer, offset, limit); + } + } + + private void onNetworkEnd( + EndFW end) + { + final long authorization = end.authorization(); + final long traceId = end.traceId(); + + if (decodeSlot == NO_SLOT) + { + state = MqttState.closeReply(state); + + cleanupStreamsUsingAbort(traceId, authorization); + + doNetworkEnd(traceId, authorization); + + decoder = decodeIgnoreAll; + } + } + + private void onNetworkAbort( + AbortFW abort) + { + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + state = MqttState.closeInitial(state); + + cleanupDecodeSlot(); + + cleanupNetwork(traceId, authorization); + } + + private void onNetworkWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + state = MqttState.openReply(state); + + assert acknowledge <= sequence; + assert sequence <= encodeSeq; + assert acknowledge >= encodeAck; + assert maximum >= encodeMax; + + encodeAck = acknowledge; + encodeMax = maximum; + encodePad = padding; + + assert encodeAck <= encodeSeq; + + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer buffer = bufferPool.buffer(encodeSlot); + final int offset = 0; + final int limit = encodeSlotOffset; + + encodeNetwork(encodeSlotTraceId, authorization, budgetId, buffer, offset, limit); + } + + final int encodeWin = encodeMax - (int) (encodeSeq - encodeAck); + final int encodeSharedCredit = Math.min(encodeBudgetMax, encodeWin - encodeSlotOffset - encodeSharedBudget); + + if (encodeSharedCredit > 0) + { + final long encodeSharedBudgetPrevious = creditor.credit(traceId, encodeBudgetIndex, encodeSharedCredit); + encodeSharedBudget += encodeSharedCredit; + + assert encodeSharedBudgetPrevious + encodeSharedCredit <= encodeBudgetMax + : String.format("%d + %d <= %d, encodeBudget = %d", + encodeSharedBudgetPrevious, encodeSharedCredit, encodeBudgetMax, encodeWin); + + assert encodeSharedCredit <= encodeBudgetMax + : String.format("%d <= %d", encodeSharedCredit, encodeBudgetMax); + } + sessionStream.doSessionWindow(traceId, authorization, encodeSlotOffset, encodeBudgetMax); + } + + private void onNetworkReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + final long authorization = reset.authorization(); + + cleanupNetwork(traceId, authorization); + } + + private void onNetworkSignal( + SignalFW signal) + { + final int signalId = signal.signalId(); + + switch (signalId) + { + case KEEP_ALIVE_TIMEOUT_SIGNAL: + onKeepAliveTimeoutSignal(signal); + break; + case PINGRESP_TIMEOUT_SIGNAL: + onPingRespTimeoutSignal(signal); + break; + case CONNACK_TIMEOUT_SIGNAL: + onConnectTimeoutSignal(signal); + break; + default: + break; + } + } + + private void onKeepAliveTimeoutSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final long authorization = signal.authorization(); + + doEncodePingReq(traceId, authorization); + keepAliveTimeoutId = NO_CANCEL_ID; + doSignalKeepAliveTimeout(); + } + + private void onPingRespTimeoutSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final long authorization = signal.authorization(); + + cleanupNetwork(traceId, authorization); + } + + private void onConnectTimeoutSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final long authorization = signal.authorization(); + + final long now = System.currentTimeMillis(); + if (now >= connackTimeoutAt) + { + cleanupStreamsUsingAbort(traceId, authorization); + doNetworkEnd(traceId, authorization); + decoder = decodeIgnoreAll; + } + } + + private void doCancelConnackTimeout() + { + if (connackTimeoutId != NO_CANCEL_ID) + { + signaler.cancel(connackTimeoutId); + connackTimeoutId = NO_CANCEL_ID; + } + } + + private int onDecodeConnack( + long traceId, + long authorization, + DirectBuffer buffer, + int progress, + int limit, + MqttConnackFW connack) + { + byte reasonCode; + decode: + { + if (connectAcked) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + + final MqttPropertiesFW properties = connack.properties(); + + reasonCode = decodeConnackProperties(properties); + + if (reasonCode != SUCCESS || connack.reasonCode() != SUCCESS) + { + break decode; + } + + + Flyweight mqttBeginEx = mqttSessionBeginExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder + .flags(flags) + .expiry((int) TimeUnit.MILLISECONDS.toSeconds(sessionExpiry)) + .qosMax(maximumQos) + .packetSizeMax(maximumPacketSize) + .capabilities(capabilities) + .clientId(clientId)) + .build(); + + sessionStream.doSessionBegin(traceId, authorization, 0, mqttBeginEx); + connectAcked = true; + + doCancelConnackTimeout(); + doSignalKeepAliveTimeout(); + } + + progress = connack.limit(); + if (reasonCode != SUCCESS) + { + doCancelConnackTimeout(); + cleanupNetwork(traceId, authorization); + decoder = decodeIgnoreAll; + } + + final Flyweight mqttBeginEx = mqttSessionBeginExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder + .flags(flags) + .expiry(sessionExpiry) + .qosMax(maximumQos) + .packetSizeMax(maximumPacketSize) + .capabilities(capabilities) + .clientId(clientId)) + .build(); + + sessionStream.doSessionBegin(traceId, authorization, 0, mqttBeginEx); + + if (connack.reasonCode() != SUCCESS) + { + sessionStream.doSessionReset(traceId, authorization, connack.reasonCode()); + cleanupNetwork(traceId, authorization); + decoder = decodeIgnoreAll; + } + + return progress; + } + + private byte decodeConnackProperties( + MqttPropertiesFW properties) + { + byte reasonCode = SUCCESS; + + final OctetsFW propertiesValue = properties.value(); + final DirectBuffer decodeBuffer = propertiesValue.buffer(); + final int decodeOffset = propertiesValue.offset(); + final int decodeLimit = propertiesValue.limit(); + + decode: + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + { + final MqttPropertyFW mqttProperty = mqttPropertyRO.wrap(decodeBuffer, decodeProgress, decodeLimit); + switch (mqttProperty.kind()) + { + case KIND_SESSION_EXPIRY: + if (isSetSessionExpiryInterval(decodablePropertyMask)) + { + sessionExpiry = 0; + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_SESSION_EXPIRY_MASK; + this.sessionExpiry = (int) mqttProperty.sessionExpiry(); + break; + case KIND_TOPIC_ALIAS_MAXIMUM: + if (isSetTopicAliasMaximum(decodablePropertyMask)) + { + topicAliasMaximum = 0; + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_TOPIC_ALIAS_MAXIMUM_MASK; + this.topicAliasMaximum = (short) (mqttProperty.topicAliasMaximum() & 0xFFFF); + break; + case KIND_MAXIMUM_QO_S: + if (isSetMaximumQos(decodablePropertyMask)) + { + maximumQos = 0; + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_MAXIMUM_QOS_MASK; + this.maximumQos = (byte) mqttProperty.maximumQoS(); + break; + case KIND_RECEIVE_MAXIMUM: + case KIND_MAXIMUM_PACKET_SIZE: + final int maxConnackPacketSize = (int) mqttProperty.maximumPacketSize(); + if (maxConnackPacketSize == 0 || isSetMaximumPacketSize(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_MAXIMUM_PACKET_SIZE_MASK; + if (maxConnackPacketSize < maximumPacketSize) + { + this.maximumPacketSize = maxConnackPacketSize; + } + break; + case KIND_RETAIN_AVAILABLE: + if (isSetRetainAvailable(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_RETAIN_AVAILABLE_MASK; + if (mqttProperty.retainAvailable() == 0) + { + this.capabilities &= ~(1 << MqttServerCapabilities.RETAIN.value()); + } + break; + case KIND_ASSIGNED_CLIENT_ID: + if (isSetAssignedClientId(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_ASSIGNED_CLIENT_IDENTIFIER_MASK; + clientId = mqttProperty.assignedClientId().asString(); + break; + case KIND_WILDCARD_SUBSCRIPTION_AVAILABLE: + if (isSetWildcardSubscriptions(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_WILDCARD_SUBSCRIPTION_AVAILABLE_MASK; + if (mqttProperty.wildcardSubscriptionAvailable() == 0) + { + this.capabilities &= ~(1 << MqttServerCapabilities.WILDCARD.value()); + } + break; + case KIND_SUBSCRIPTION_IDS_AVAILABLE: + if (isSetSubscriptionIdentifiers(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_SUBSCRIPTION_IDENTIFIERS_MASK; + if (mqttProperty.subscriptionIdsAvailable() == 0) + { + this.capabilities &= ~(1 << MqttServerCapabilities.SUBSCRIPTION_IDS.value()); + } + break; + case KIND_SHARED_SUBSCRIPTION_AVAILABLE: + if (isSetSharedSubscriptions(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_SHARED_SUBSCRIPTION_AVAILABLE_MASK; + if (mqttProperty.sharedSubscriptionAvailable() == 0) + { + this.capabilities &= ~(1 << MqttServerCapabilities.SHARED_SUBSCRIPTIONS.value()); + } + break; + case KIND_SERVER_KEEP_ALIVE: + if (isSetServerKeepAlive(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNACK_SHARED_SUBSCRIPTION_AVAILABLE_MASK; + keepAliveMillis = SECONDS.toMillis(mqttProperty.serverKeepAlive()); + pingRespTimeoutMillis = (long) (keepAliveMillis * 0.5); + break; + case KIND_USER_PROPERTY: + // TODO + break; + case KIND_AUTHENTICATION_METHOD: + reasonCode = BAD_AUTHENTICATION_METHOD; + break decode; + case KIND_AUTHENTICATION_DATA: + // TODO + break; + default: + reasonCode = MALFORMED_PACKET; + break decode; + } + + decodeProgress = mqttProperty.limit(); + } + + return reasonCode; + } + + private void onDecodePingResp( + long traceId, + long authorization, + MqttPingRespFW ping) + { + doCancelPingRespTimeout(); + } + + private int onDecodeSuback( + long traceId, + long authorization, + DirectBuffer buffer, + int progress, + int limit, + MqttSubackFW suback) + { + final int packetId = suback.packetId(); + final OctetsFW decodePayload = suback.payload(); + + final DirectBuffer decodeBuffer = decodePayload.buffer(); + final int decodeOffset = decodePayload.offset(); + final int decodeLimit = decodePayload.limit(); + + final List unackedSubscriptions = sessionStream.unAckedSubscriptionsByPacketId.remove(packetId); + MqttSessionStateFW.Builder sessionStateBuilder = + mqttSessionStateRW.wrap(sessionStateBuffer, 0, sessionStateBuffer.capacity()); + + sessionStream.subscriptions.stream().filter(s -> !unackedSubscriptions.contains(s)).forEach(s -> + sessionStateBuilder.subscriptionsItem(si -> + si.subscriptionId(s.id) + .qos(s.qos) + .flags(s.flags) + .pattern(s.filter))); + + int i = 0; + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + { + final MqttSubackPayloadFW subackPayload = + mqttSubackPayloadRO.tryWrap(decodeBuffer, decodeProgress, decodeLimit); + if (subackPayload == null) + { + break; + } + decodeProgress = subackPayload.limit(); + + final Subscription subscription = unackedSubscriptions.get(i++); + sessionStateBuilder.subscriptionsItem(si -> + si.subscriptionId(subscription.id) + .qos(subscription.qos) + .flags(subscription.flags) + .reasonCode(subackPayload.reasonCode()) + .pattern(subscription.filter)); + } + final MqttSessionStateFW sessionState = sessionStateBuilder.build(); + sessionStream.doSessionData(traceId, authorization, sessionState.sizeof(), EMPTY_OCTETS, sessionState); + + progress = suback.limit(); + return progress; + } + + private int onDecodeUnsuback( + long traceId, + long authorization, + DirectBuffer buffer, + int progress, + int limit, + MqttUnsubackFW unsuback) + { + final int packetId = unsuback.packetId(); + final OctetsFW decodePayload = unsuback.payload(); + + final DirectBuffer decodeBuffer = decodePayload.buffer(); + final int decodeOffset = decodePayload.offset(); + final int decodeLimit = decodePayload.limit(); + + final List unackedSubscriptions = sessionStream.unAckedSubscriptionsByPacketId.remove(packetId); + sessionStream.subscriptions.removeAll(unackedSubscriptions); + + MqttSessionStateFW.Builder sessionStateBuilder = + mqttSessionStateRW.wrap(sessionStateBuffer, 0, sessionStateBuffer.capacity()); + sessionStream.subscriptions.forEach(s -> + sessionStateBuilder.subscriptionsItem(si -> + si.subscriptionId(s.id) + .qos(s.qos) + .flags(s.flags) + .pattern(s.filter))); + int i = 0; + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + { + final MqttUnsubackPayloadFW unsubackPayload = + mqttUnsubackPayloadRO.tryWrap(decodeBuffer, decodeProgress, decodeLimit); + if (unsubackPayload == null) + { + break; + } + decodeProgress = unsubackPayload.limit(); + + final int reasonCode = unsubackPayload.reasonCode(); + if (reasonCode != SUCCESS) + { + final Subscription subscription = unackedSubscriptions.get(i); + sessionStateBuilder.subscriptionsItem(si -> + si.subscriptionId(subscription.id) + .qos(subscription.qos) + .flags(subscription.flags) + .reasonCode(reasonCode) + .pattern(subscription.filter)); + } + i++; + } + final MqttSessionStateFW sessionState = sessionStateBuilder.build(); + sessionStream.doSessionData(traceId, authorization, sessionState.sizeof(), EMPTY_OCTETS, sessionState); + + progress = unsuback.limit(); + + return progress; + } + + private void onDecodePublish( + long traceId, + long authorization, + int reserved, + OctetsFW payload, + MqttSubscribeStream stream) + { + final MqttDataExFW.Builder builder = mqttPublishDataExRW.wrap(dataExtBuffer, 0, dataExtBuffer.capacity()) + .typeId(mqttTypeId) + .subscribe(s -> + { + s.topic(mqttPublishHeaderRO.topic); + s.qos(mqttPublishHeaderRO.qos); + s.flags(mqttPublishHeaderRO.flags); + s.subscriptionIds(subscriptionIdsRW.build()); + s.expiryInterval(mqttPublishHeaderRO.expiryInterval); + s.contentType(mqttPublishHeaderRO.contentType); + s.format(f -> f.set(mqttPublishHeaderRO.payloadFormat)); + s.responseTopic(mqttPublishHeaderRO.responseTopic); + s.correlation(c -> c.bytes(mqttPublishHeaderRO.correlationData)); + final Array32FW userProperties = userPropertiesRW.build(); + userProperties.forEach(c -> s.propertiesItem(p -> p.key(c.key()).value(c.value()))); + }); + + + final MqttDataExFW dataEx = builder.build(); + if (stream != null) + { + stream.doSubscribeData(traceId, authorization, reserved, payload, dataEx); + } + } + + private void onDecodeDisconnect( + long traceId, + long authorization, + MqttDisconnectFW disconnect) + { + byte reasonCode = decodeDisconnectProperties(disconnect.properties()); + + if (reasonCode != SUCCESS) + { + onDecodeError(traceId, authorization, reasonCode); + decoder = decodeIgnoreAll; + } + else + { + if (disconnect.reasonCode() != SUCCESS) + { + sessionStream.doSessionReset(traceId, authorization, disconnect.reasonCode()); + } + } + + state = MqttState.closingInitial(state); + closeStreams(traceId, authorization); + doNetworkEnd(traceId, authorization); + } + + private byte decodeDisconnectProperties( + MqttPropertiesFW properties) + { + byte reasonCode = SUCCESS; + + final OctetsFW propertiesValue = properties.value(); + final DirectBuffer decodeBuffer = propertiesValue.buffer(); + final int decodeOffset = propertiesValue.offset(); + final int decodeLimit = propertiesValue.limit(); + + decode: + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + { + final MqttPropertyFW mqttProperty = mqttPropertyRO.wrap(decodeBuffer, decodeProgress, decodeLimit); + switch (mqttProperty.kind()) + { + case KIND_SESSION_EXPIRY: + reasonCode = PROTOCOL_ERROR; + break decode; + default: + break; + } + + decodeProgress = mqttProperty.limit(); + } + + return reasonCode; + } + + private void onDecodeError( + long traceId, + long authorization, + int reasonCode) + { + cleanupStreamsUsingAbort(traceId, authorization); + doNetworkEnd(traceId, authorization); + } + + private void doNetworkBegin( + long traceId, + long authorization, + long affinity) + { + if (!MqttState.initialOpening(state)) + { + state = MqttState.openingInitial(state); + + network = newStream(this::onNetwork, originId, routedId, initialId, initialSeq, initialAck, + initialMax, traceId, authorization, affinity, EMPTY_OCTETS); + } + } + + private void doNetworkData( + long traceId, + long authorization, + long budgetId, + Flyweight flyweight) + { + doNetworkData(traceId, authorization, budgetId, flyweight.buffer(), flyweight.offset(), flyweight.limit()); + } + + private void doNetworkData( + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + if (encodeSlot != NO_SLOT) + { + final MutableDirectBuffer encodeBuffer = bufferPool.buffer(encodeSlot); + encodeBuffer.putBytes(encodeSlotOffset, buffer, offset, limit - offset); + encodeSlotOffset += limit - offset; + encodeSlotTraceId = traceId; + + buffer = encodeBuffer; + offset = 0; + limit = encodeSlotOffset; + } + + encodeNetwork(traceId, authorization, budgetId, buffer, offset, limit); + } + + private void doNetworkEnd( + long traceId, + long authorization) + { + if (!MqttState.initialClosed(state)) + { + state = MqttState.closeInitial(state); + + cleanupBudgetCreditor(); + cleanupEncodeSlot(); + + doEnd(network, originId, routedId, initialId, encodeSeq, encodeAck, encodeMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void doNetworkAbort( + long traceId, + long authorization) + { + if (!MqttState.replyClosed(state)) + { + state = MqttState.closeReply(state); + + cleanupBudgetCreditor(); + cleanupEncodeSlot(); + + doAbort(network, originId, routedId, initialId, encodeSeq, encodeAck, encodeMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void doNetworkReset( + long traceId, + long authorization) + { + if (!MqttState.initialClosed(state)) + { + state = MqttState.closeInitial(state); + + cleanupDecodeSlot(); + + doReset(network, originId, routedId, initialId, decodeSeq, decodeAck, decodeMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void doNetworkWindow( + long traceId, + long authorization, + int padding, + long budgetId) + { + doNetworkWindow(traceId, authorization, padding, budgetId, decodeSlotReserved, decodeMax); + } + + private void doNetworkWindow( + long traceId, + long authorization, + int padding, + long budgetId, + int minReplyNoAck, + int minReplyMax) + { + final long newReplyAck = Math.max(decodeSeq - minReplyNoAck, decodeAck); + + if (newReplyAck > decodeAck || minReplyMax > decodeMax || !MqttState.initialOpened(state)) + { + decodeAck = newReplyAck; + assert decodeAck <= decodeSeq; + + decodeMax = minReplyMax; + + state = MqttState.openInitial(state); + + doWindow(network, originId, routedId, replyId, decodeSeq, decodeAck, decodeMax, + traceId, authorization, budgetId, padding); + } + } + + private void doEncodePublish( + long traceId, + long authorization, + int flags, + OctetsFW payload, + OctetsFW extension, + String topic) + { + if ((flags & 0x02) != 0) + { + final MqttDataExFW mqttDataEx = extension.get(mqttPublishDataExRO::tryWrap); + final int payloadSize = payload.sizeof(); + + assert mqttDataEx.kind() == MqttBeginExFW.KIND_PUBLISH; + final MqttPublishDataExFW mqttPublishDataEx = mqttDataEx.publish(); + + final int deferred = mqttPublishDataEx.deferred(); + final int expiryInterval = mqttPublishDataEx.expiryInterval(); + final String16FW contentType = mqttPublishDataEx.contentType(); + final String16FW responseTopic = mqttPublishDataEx.responseTopic(); + final MqttBinaryFW correlation = mqttPublishDataEx.correlation(); + final MqttPayloadFormatFW format = mqttPublishDataEx.format(); + final Array32FW properties = + mqttPublishDataEx.properties(); + + final int topicLength = topic.length(); + + AtomicInteger propertiesSize = new AtomicInteger(); + + final int publishFlags = mqttPublishDataEx.flags(); + final int qos = mqttPublishDataEx.qos(); + + final int publishNetworkTypeAndFlags = PUBLISH_TYPE << 4 | + calculatePublishNetworkFlags(PUBLISH_TYPE << 4 | publishFlags, qos); + + if (expiryInterval != -1) + { + mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) + .expiryInterval(expiryInterval) + .build(); + propertiesSize.set(mqttPropertyRW.limit()); + } + + if (contentType.value() != null) + { + mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) + .contentType(contentType.asString()) + .build(); + propertiesSize.set(mqttPropertyRW.limit()); + } + + if (!format.get().equals(MqttPayloadFormat.NONE)) + { + mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) + .payloadFormat((byte) mqttPublishDataEx.format().get().ordinal()) + .build(); + propertiesSize.set(mqttPropertyRW.limit()); + } + + if (responseTopic.value() != null) + { + mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) + .responseTopic(responseTopic.asString()) + .build(); + propertiesSize.set(mqttPropertyRW.limit()); + } + + if (correlation.length() != -1) + { + mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) + .correlationData(a -> a.bytes(correlation.bytes())) + .build(); + propertiesSize.set(mqttPropertyRW.limit()); + } + + properties.forEach(p -> + { + mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) + .userProperty(c -> c.key(p.key()).value(p.value())) + .build(); + propertiesSize.set(mqttPropertyRW.limit()); + }); + + final int propertiesSize0 = propertiesSize.get(); + final MqttPublishFW publish = + mqttPublishRW.wrap(writeBuffer, DataFW.FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()) + .typeAndFlags(publishNetworkTypeAndFlags) + .remainingLength(3 + topicLength + propertiesSize.get() + payloadSize + deferred) + .topicName(topic) + .properties(p -> p.length(propertiesSize0) + .value(propertyBuffer, 0, propertiesSize0)) + .payload(payload) + .build(); + + doNetworkData(traceId, authorization, 0L, publish); + } + else + { + doNetworkData(traceId, authorization, 0L, payload); + } + } + + private int calculatePublishNetworkFlags(int applicationTypeAndFlags, int qos) + { + int flags = 0; + + if ((applicationTypeAndFlags & RETAIN_FLAG) != 0) + { + flags |= RETAIN_MASK; + } + + if (qos == MqttQoS.AT_LEAST_ONCE.value()) + { + flags |= PUBLISH_QOS1_MASK; + } + else if (qos == MqttQoS.EXACTLY_ONCE.value()) + { + flags |= PUBLISH_QOS2_MASK; + } + return flags; + } + + private void doEncodeConnect( + long traceId, + long authorization, + String clientId, + int flags, + int sessionExpiry, + MqttWillMessageFW willMessage) + { + int propertiesSize = 0; + + MqttPropertyFW mqttProperty; + + //TODO: remove this once we support large messages + mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) + .maximumPacketSize(maximumPacketSize) + .build(); + propertiesSize = mqttProperty.limit(); + + if (sessionExpiry != 0) + { + mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) + .sessionExpiry(sessionExpiry) + .build(); + propertiesSize = mqttProperty.limit(); + } + MqttWillFW will = null; + if (willMessage != null) + { + final int expiryInterval = willMessage.expiryInterval(); + final String16FW contentType = willMessage.contentType(); + final String16FW responseTopic = willMessage.responseTopic(); + final MqttBinaryFW correlation = willMessage.correlation(); + final MqttPayloadFormatFW format = willMessage.format(); + final Array32FW properties = + willMessage.properties(); + + AtomicInteger willPropertiesSize = new AtomicInteger(); + if (expiryInterval != -1) + { + mqttWillPropertyRW.wrap(willPropertyBuffer, willPropertiesSize.get(), willPropertyBuffer.capacity()) + .expiryInterval(expiryInterval) + .build(); + willPropertiesSize.set(mqttWillPropertyRW.limit()); + } + + if (contentType.value() != null) + { + mqttWillPropertyRW.wrap(willPropertyBuffer, willPropertiesSize.get(), willPropertyBuffer.capacity()) + .contentType(contentType.asString()) + .build(); + willPropertiesSize.set(mqttWillPropertyRW.limit()); + } + + if (!format.get().equals(MqttPayloadFormat.NONE)) + { + mqttWillPropertyRW.wrap(willPropertyBuffer, willPropertiesSize.get(), willPropertyBuffer.capacity()) + .payloadFormat((byte) format.get().ordinal()) + .build(); + willPropertiesSize.set(mqttWillPropertyRW.limit()); + } + + if (responseTopic.value() != null) + { + mqttWillPropertyRW.wrap(willPropertyBuffer, willPropertiesSize.get(), willPropertyBuffer.capacity()) + .responseTopic(responseTopic.asString()) + .build(); + willPropertiesSize.set(mqttWillPropertyRW.limit()); + } + + if (correlation.length() != -1) + { + mqttWillPropertyRW.wrap(willPropertyBuffer, willPropertiesSize.get(), willPropertyBuffer.capacity()) + .correlationData(a -> a.bytes(correlation.bytes())) + .build(); + willPropertiesSize.set(mqttWillPropertyRW.limit()); + } + + properties.forEach(p -> + { + mqttWillPropertyRW.wrap(willPropertyBuffer, willPropertiesSize.get(), willPropertyBuffer.capacity()) + .userProperty(c -> c.key(p.key()).value(p.value())) + .build(); + willPropertiesSize.set(mqttWillPropertyRW.limit()); + }); + + will = willMessageRW.wrap(willMessageBuffer, 0, willMessageBuffer.capacity()) + .properties(p -> p.length(willPropertiesSize.get()) + .value(willPropertyBuffer, 0, willPropertiesSize.get())) + .topic(willMessage.topic()) + .payload(p -> p.bytes(willMessage.payload().bytes())) + .build(); + } + + final int propertiesSize0 = propertiesSize; + final int willSize = will != null ? will.sizeof() : 0; + flags |= will != null ? (WILL_FLAG_MASK | ((willMessage.flags() & RETAIN_MASK) != 0 ? WILL_RETAIN_MASK : 0)) : 0; + final MqttConnectFW connect = + mqttConnectRW.wrap(writeBuffer, FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()) + .typeAndFlags(0x10) + .remainingLength(11 + propertiesSize0 + clientId.length() + 2 + willSize) + .protocolName(MQTT_PROTOCOL_NAME) + .protocolVersion(MQTT_PROTOCOL_VERSION) + .flags(flags) + .keepAlive((int) MILLISECONDS.toSeconds(keepAliveMillis)) + .properties(p -> p.length(propertiesSize0) + .value(propertyBuffer, 0, propertiesSize0)) + .clientId(clientId) + .build(); + + doNetworkData(traceId, authorization, 0L, connect); + if (will != null) + { + doNetworkData(traceId, authorization, 0L, will); + } + } + + private void doEncodeSubscribe( + long traceId, + long authorization, + List subscriptions, + int packetId) + { + int propertiesSize = 0; + + MqttPropertyFW mqttProperty; + + final int subscriptionId = subscriptions.get(0).id; + if (subscriptionId != 0 && !generatedSubscriptionId(subscriptionId)) + { + mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) + .subscriptionId(i -> i.set(subscriptionId)) + .build(); + propertiesSize = mqttProperty.limit(); + } + + final int propertiesSize0 = propertiesSize; + + final MutableDirectBuffer encodeBuffer = payloadBuffer; + final int encodeOffset = 0; + final int encodeLimit = payloadBuffer.capacity(); + + int encodeProgress = encodeOffset; + + for (Subscription s : subscriptions) + { + final int flags = calculateSubscribeFlags(s.flags); + final MqttSubscribePayloadFW subscribePayload = + mqttSubscribePayloadRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .filter(s.filter) + .options(flags) + .build(); + encodeProgress = subscribePayload.limit(); + } + + final OctetsFW encodePayload = octetsRO.wrap(encodeBuffer, encodeOffset, encodeProgress); + final MqttSubscribeFW subscribe = + mqttSubscribeRW.wrap(writeBuffer, FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()) + .typeAndFlags(0x82) + .remainingLength(3 + propertiesSize0 + encodePayload.sizeof()) + .packetId(packetId) + .properties(p -> p.length(propertiesSize0) + .value(propertyBuffer, 0, propertiesSize0)) + .payload(encodePayload) + .build(); + + sessionStream.unAckedSubscriptionsByPacketId.put(packetId, subscriptions); + doNetworkData(traceId, authorization, 0L, subscribe); + } + + private boolean generatedSubscriptionId( + int subscriptionId) + { + return (subscriptionId & GENERATED_SUBSCRIPTION_ID_MASK) == GENERATED_SUBSCRIPTION_ID_MASK; + } + + private void doEncodeUnsubscribe( + long traceId, + long authorization, + List subscriptions, + int packetId) + { + final MutableDirectBuffer encodeBuffer = payloadBuffer; + final int encodeOffset = 0; + final int encodeLimit = payloadBuffer.capacity(); + + int encodeProgress = encodeOffset; + + for (Subscription s : subscriptions) + { + final MqttUnsubscribePayloadFW unsubscribePayload = + mqttUnsubscribePayloadRW.wrap(encodeBuffer, encodeProgress, encodeLimit) + .filter(s.filter) + .build(); + encodeProgress = unsubscribePayload.limit(); + } + + final OctetsFW encodePayload = octetsRO.wrap(encodeBuffer, encodeOffset, encodeProgress); + final MqttUnsubscribeFW unsubscribe = + mqttUnsubscribeRW.wrap(writeBuffer, FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()) + .typeAndFlags(0xa2) + .remainingLength(3 + encodePayload.sizeof()) + .packetId(packetId) + .properties(p -> p.length(0) + .value(propertyBuffer, 0, 0)) + .payload(encodePayload) + .build(); + + sessionStream.unAckedSubscriptionsByPacketId.put(packetId, subscriptions); + doNetworkData(traceId, authorization, 0L, unsubscribe); + } + + private void doEncodePingReq( + long traceId, + long authorization) + { + final MqttPingReqFW pingReq = + mqttPingReqRW.wrap(writeBuffer, FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()) + .typeAndFlags(0xc0) + .remainingLength(0x00) + .build(); + + doNetworkData(traceId, authorization, 0L, pingReq); + doSignalPingRespTimeout(); + } + + private void doEncodeDisconnect( + long traceId, + long authorization, + int reasonCode) + { + int propertiesSize = 0; + + final int propertySize0 = propertiesSize; + final MqttDisconnectFW disconnect = + mqttDisconnectRW.wrap(writeBuffer, FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()) + .typeAndFlags(0xe0) + .remainingLength(2 + propertySize0) + .reasonCode(reasonCode & 0xff) + .properties(p -> p.length(propertySize0) + .value(propertyBuffer, 0, propertySize0)) + .build(); + + doNetworkData(traceId, authorization, 0L, disconnect); + } + + private void encodeNetwork( + long traceId, + long authorization, + long budgetId, + DirectBuffer buffer, + int offset, + int limit) + { + final int maxLength = limit - offset; + final int encodeWin = encodeMax - (int) (encodeSeq - encodeAck + encodeSlotOffset); + final int length = Math.min(maxLength, Math.max(encodeWin - encodePad, 0)); + + if (length > 0) + { + final int reserved = length + encodePad; + + doData(network, originId, routedId, initialId, encodeSeq, encodeAck, encodeMax, + traceId, authorization, budgetId, reserved, buffer, offset, length, EMPTY_OCTETS); + + encodeSeq += reserved; + + assert encodeSeq <= encodeAck + encodeMax : + String.format("%d <= %d + %d", encodeSeq, encodeAck, encodeMax); + } + + final int remaining = maxLength - length; + if (remaining > 0) + { + if (encodeSlot == NO_SLOT) + { + encodeSlot = bufferPool.acquire(replyId); + assert encodeSlotOffset == 0; + } + + if (encodeSlot == NO_SLOT) + { + cleanupNetwork(traceId, authorization); + } + else + { + final MutableDirectBuffer encodeBuffer = bufferPool.buffer(encodeSlot); + encodeBuffer.putBytes(0, buffer, offset + length, remaining); + encodeSlotOffset = remaining; + } + } + else + { + cleanupEncodeSlot(); + + if (publishStreams.isEmpty() && subscribeStreams.isEmpty() && decoder == decodeIgnoreAll) + { + doNetworkEnd(traceId, authorization); + } + } + } + + private void decodeNetwork( + long traceId) + { + if (decodeSlot != NO_SLOT) + { + final long authorization = 0L; // TODO; + final long budgetId = 0L; // TODO + + final DirectBuffer buffer = bufferPool.buffer(decodeSlot); + final int offset = 0; + final int limit = decodeSlotOffset; + final int reserved = decodeSlotReserved; + + decodeNetwork(traceId, authorization, budgetId, reserved, buffer, offset, limit); + } + } + + private void decodeNetwork( + long traceId, + long authorization, + long budgetId, + int reserved, + DirectBuffer buffer, + int offset, + int limit) + { + MqttClientDecoder previous = null; + int progress = offset; + while (progress <= limit && previous != decoder) + { + previous = decoder; + progress = decoder.decode(this, traceId, authorization, budgetId, buffer, progress, limit); + } + + if (progress < limit) + { + if (decodeSlot == NO_SLOT) + { + decodeSlot = bufferPool.acquire(initialId); + } + + if (decodeSlot == NO_SLOT) + { + cleanupNetwork(traceId, authorization); + } + else + { + final MutableDirectBuffer slotBuffer = bufferPool.buffer(decodeSlot); + slotBuffer.putBytes(0, buffer, progress, limit - progress); + decodeSlotOffset = limit - progress; + decodeSlotReserved = (int) ((long) reserved * (limit - progress) / (limit - offset)); + } + } + else + { + cleanupDecodeSlot(); + + if (MqttState.initialClosing(state)) + { + state = MqttState.closeInitial(state); + cleanupStreamsUsingAbort(traceId, authorization); + doNetworkEnd(traceId, authorization); + } + } + + if (!MqttState.initialClosed(state)) + { + doNetworkWindow(traceId, authorization, 0, budgetId, decodeSlotReserved, decodeMax); + } + } + + private void cleanupNetwork( + long traceId, + long authorization) + { + cleanupStreamsUsingAbort(traceId, authorization); + + doNetworkReset(traceId, authorization); + doNetworkAbort(traceId, authorization); + } + + private void cleanupStreamsUsingAbort( + long traceId, + long authorization) + { + publishStreams.forEach(s -> s.cleanupAbort(traceId, authorization)); + subscribeStreams.values().forEach(s -> s.cleanupAbort(traceId, authorization)); + if (sessionStream != null) + { + sessionStream.cleanupAbort(traceId, authorization); + } + } + + private void closeStreams( + long traceId, + long authorization) + { + publishStreams.forEach(s -> s.doPublishEnd(traceId, authorization)); + subscribeStreams.values().forEach(s -> s.doSubscribeEnd(traceId, authorization)); + if (sessionStream != null) + { + sessionStream.cleanupEnd(traceId, authorization); + } + } + + private void cleanupBudgetCreditor() + { + if (encodeBudgetIndex != NO_CREDITOR_INDEX) + { + creditor.release(encodeBudgetIndex); + encodeBudgetIndex = NO_CREDITOR_INDEX; + } + } + + private void cleanupDecodeSlot() + { + if (decodeSlot != NO_SLOT) + { + bufferPool.release(decodeSlot); + decodeSlot = NO_SLOT; + decodeSlotOffset = 0; + decodeSlotReserved = 0; + } + } + + private void cleanupEncodeSlot() + { + if (encodeSlot != NO_SLOT) + { + bufferPool.release(encodeSlot); + encodeSlot = NO_SLOT; + encodeSlotOffset = 0; + encodeSlotTraceId = 0; + } + } + + private void doSignalKeepAliveTimeout() + { + if (keepAliveMillis > 0) + { + keepAliveTimeoutAt = System.currentTimeMillis() + keepAliveMillis; + + if (keepAliveTimeoutId == NO_CANCEL_ID) + { + keepAliveTimeoutId = + signaler.signalAt(keepAliveTimeoutAt, originId, routedId, initialId, KEEP_ALIVE_TIMEOUT_SIGNAL, 0); + } + } + } + + private void doSignalConnackTimeout() + { + connackTimeoutAt = System.currentTimeMillis() + connackTimeoutMillis; + + if (connackTimeoutId == NO_CANCEL_ID) + { + connackTimeoutId = signaler.signalAt(connackTimeoutAt, originId, routedId, initialId, CONNACK_TIMEOUT_SIGNAL, 0); + } + } + + private void doSignalPingRespTimeout() + { + pingRespTimeoutAt = System.currentTimeMillis() + pingRespTimeoutMillis; + + if (pingRespTimeoutId == NO_CANCEL_ID) + { + pingRespTimeoutId = + signaler.signalAt(pingRespTimeoutAt, originId, routedId, initialId, PINGRESP_TIMEOUT_SIGNAL, 0); + } + } + + private void doCancelPingRespTimeout() + { + if (pingRespTimeoutId != NO_CANCEL_ID) + { + signaler.cancel(pingRespTimeoutId); + pingRespTimeoutId = NO_CANCEL_ID; + } + } + + private int calculateSubscribeFlags( + int options) + { + int flags = 0; + if ((options & SEND_RETAINED_FLAG) == 0) + { + flags |= DO_NOT_SEND_RETAINED_MASK; + } + + if ((options & RETAIN_AS_PUBLISHED_FLAG) != 0) + { + flags |= RETAIN_AS_PUBLISHED_MASK; + } + + if ((options & NO_LOCAL_FLAG) != 0) + { + flags |= NO_LOCAL_FLAG_MASK; + } + + + return flags; + } + + private boolean existStreamForId( + int subscriptionId) + { + return sessionStream.subscriptions.stream().anyMatch(s -> s.id == subscriptionId); + } + + private boolean existStreamForTopic( + String topic) + { + boolean match = sessionStream.subscriptions.stream().anyMatch(s -> + { + String regex = s.filter.replace("#", ".*").replace("+", "[^/]+"); + return Pattern.matches(regex, topic); + }); + + if (!match) + { + match = sessionStream.unAckedSubscriptionsByPacketId.values().stream().anyMatch(ss -> + ss.stream().anyMatch(s -> + { + String regex = s.filter.replace("#", ".*").replace("+", "[^/]+"); + return Pattern.matches(regex, topic); + })); + } + + return match; + } + + private int nextPacketId() + { + final int packetId = packetIdCounter.incrementAndGet(); + if (packetId == Integer.MAX_VALUE) + { + packetIdCounter.set(0); + } + return packetId; + } + } + + private final class MqttSessionStream + { + private final MqttClient client; + private final List subscriptions; + private final Int2ObjectHashMap> unAckedSubscriptionsByPacketId; + private MessageConsumer application; + + private long originId; + private long routedId; + private long initialId; + private long replyId; + private long budgetId; + + private BudgetDebitor debitor; + private long debitorIndex = NO_DEBITOR_INDEX; + + private long initialSeq; + private long initialAck; + private int initialMax; + private int initialPad; + + private long replySeq; + private long replyAck; + private int replyMax; + private long replyBud; + private int replyPad; + private int state; + + MqttSessionStream( + MqttClient client, + MessageConsumer application, + long originId, + long routedId, + long initialId) + { + this.client = client; + this.application = application; + this.subscriptions = new ArrayList<>(); + this.unAckedSubscriptionsByPacketId = new Int2ObjectHashMap<>(); + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void onSession( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onSessionBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onSessionData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onSessionEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onSessionAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onSessionWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onSessionReset(reset); + break; + } + } + + private void onSessionWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final boolean wasOpen = MqttState.replyOpened(state); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyBud = budgetId; + replyPad = padding; + state = MqttState.openReply(state); + + assert initialAck <= initialSeq; + + if (budgetId != 0L && debitorIndex == NO_DEBITOR_INDEX) + { + debitor = supplyDebitor.apply(budgetId); + debitorIndex = debitor.acquire(budgetId, initialId, client::decodeNetwork); + } + + if (MqttState.initialClosing(state) && !MqttState.initialClosed(state)) + { + doSessionEnd(traceId, authorization); + } + + if (!wasOpen) + { + doSessionData(traceId, authorization, 0, EMPTY_OCTETS, EMPTY_OCTETS); + } + } + + private void onSessionReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + final long authorization = reset.authorization(); + + state = MqttState.closeReply(state); + + client.doNetworkReset(traceId, authorization); + } + + private void onSessionBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + final OctetsFW extension = begin.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + initialMax = maximum; + state = MqttState.openingInitial(state); + + client.doNetworkBegin(traceId, authorization, affinity); + + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + + assert mqttBeginEx.kind() == MqttBeginExFW.KIND_SESSION; + final MqttSessionBeginExFW mqttSessionBeginEx = mqttBeginEx.session(); + + client.clientId = mqttSessionBeginEx.clientId().asString(); + client.flags = mqttSessionBeginEx.flags(); + client.sessionExpiry = mqttSessionBeginEx.expiry(); + + if (!isSetWillFlag(mqttSessionBeginEx.flags())) + { + client.doEncodeConnect(traceId, authorization, client.clientId, client.flags, client.sessionExpiry, null); + client.doSignalConnackTimeout(); + } + doSessionWindow(traceId, authorization, client.encodeSlotOffset, encodeBudgetMax); + } + + private void onSessionData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final int reserved = data.reserved(); + final long authorization = data.authorization(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge <= initialAck; + + initialSeq = sequence + reserved; + client.encodeSharedBudget -= reserved; + + assert initialAck <= initialSeq; + + if (initialSeq > initialAck + initialMax) + { + doSessionReset(traceId, authorization); + client.doNetworkAbort(traceId, authorization); + } + else + { + + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final MqttDataExFW mqttDataEx = + dataEx != null && dataEx.typeId() == mqttTypeId ? extension.get(mqttDataExRO::tryWrap) : null; + final MqttSessionDataExFW mqttSessionDataEx = + mqttDataEx != null && mqttDataEx.kind() == MqttDataExFW.KIND_SESSION ? mqttDataEx.session() : null; + + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + + switch (mqttSessionDataEx.kind().get()) + { + case WILL: + MqttWillMessageFW willMessage = mqttWillMessageRO.tryWrap(buffer, offset, limit); + client.doEncodeConnect(traceId, authorization, client.clientId, client.flags, + client.sessionExpiry, willMessage); + client.doSignalConnackTimeout(); + break; + case STATE: + MqttSessionStateFW sessionState = mqttSessionStateRO.tryWrap(buffer, offset, limit); + + final List newSubscribeState = new ArrayList<>(); + sessionState.subscriptions().forEach(filter -> + { + Subscription subscription = new Subscription(); + subscription.id = (int) filter.subscriptionId(); + subscription.filter = filter.pattern().asString(); + subscription.flags = filter.flags(); + subscription.qos = filter.qos(); + newSubscribeState.add(subscription); + }); + + + final List newSubscriptions = newSubscribeState.stream() + .filter(s -> !subscriptions.contains(s)) + .collect(Collectors.toList()); + + final List oldSubscriptions = subscriptions.stream() + .filter(s -> !newSubscribeState.contains(s)) + .collect(Collectors.toList()); + final int packetId = client.nextPacketId(); + + if (newSubscriptions.size() > 0) + { + client.doEncodeSubscribe(traceId, authorization, newSubscriptions, packetId); + } + if (oldSubscriptions.size() > 0) + { + client.doEncodeUnsubscribe(traceId, authorization, oldSubscriptions, packetId); + } + client.sessionStream.subscriptions.addAll(newSubscriptions); + client.sessionStream.subscriptions.removeAll(oldSubscriptions); + break; + } + } + } + + private void onSessionEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttState.closeInitial(state); + + assert initialAck <= initialSeq; + + client.doEncodeDisconnect(traceId, authorization, SUCCESS); + client.doNetworkEnd(traceId, authorization); + + doSessionEnd(traceId, authorization); + } + + private void onSessionAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttState.closeInitial(state); + + assert initialAck <= initialSeq; + + client.doNetworkAbort(traceId, authorization); + } + + private void doSessionData( + long traceId, + long authorization, + int reserved, + Flyweight dataEx, + Flyweight payload) + { + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + final int length = limit - offset; + + if (!MqttState.closed(state)) + { + doData(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, reserved, buffer, offset, length, dataEx); + + replySeq += reserved; + assert replySeq <= replyAck + replyMax; + } + } + + private void cleanupAbort( + long traceId, + long authorization) + { + doSessionAbort(traceId, authorization); + doSessionReset(traceId, authorization); + } + + private void cleanupEnd( + long traceId, + long authorization) + { + doSessionEnd(traceId, authorization); + } + + private void doSessionAbort( + long traceId, + long authorization) + { + if (!MqttState.replyClosed(state)) + { + state = MqttState.closeReply(state); + + doAbort(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void doSessionWindow( + long traceId, + long authorization, + int minInitialNoAck, + int minInitialMax) + { + if (MqttState.replyOpened(client.state)) + { + final long newInitialAck = Math.max(initialSeq - minInitialNoAck, initialAck); + + if (newInitialAck > initialAck || minInitialMax > initialMax || !MqttState.initialOpened(state)) + { + initialAck = newInitialAck; + assert initialAck <= initialSeq; + + initialMax = minInitialMax; + + doWindow(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, client.encodeBudgetId, PUBLISH_FRAMING); + } + } + } + + private void doSessionReset( + long traceId, + long authorization, + int reasonCode) + { + if (!MqttState.initialClosed(state)) + { + Flyweight resetEx = mqttResetExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .reasonCode(reasonCode) + .build(); + + state = MqttState.closeInitial(state); + + doReset(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, resetEx); + } + } + + private void doSessionReset( + long traceId, + long authorization) + { + if (!MqttState.initialClosed(state)) + { + state = MqttState.closeInitial(state); + + doReset(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + public void doSessionBegin( + long traceId, + long authorization, + long affinity, + Flyweight extension) + { + state = MqttState.openingReply(state); + + doBegin(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, extension); + } + + private void doSessionEnd( + long traceId, + long authorization) + { + if (!MqttState.replyClosed(state)) + { + state = MqttState.closeReply(state); + + doEnd(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + } + } + } + + private class MqttSubscribeStream + { + private final MessageConsumer application; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private long budgetId; + + private MqttClient client; + private BudgetDebitor debitor; + private long debitorIndex = NO_DEBITOR_INDEX; + + private long initialSeq; + private long initialAck; + private int initialMax; + private int initialPad; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private int state; + private List subscriptions; + + MqttSubscribeStream( + MqttClient client, + MessageConsumer application, + long originId, + long routedId, + long initialId) + { + this.client = client; + this.application = application; + this.subscriptions = new ArrayList<>(); + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void onSubscribe( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onSubscribeBegin(begin); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onSubscribeFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onSubscribeEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onSubscribeAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onSubscribeWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onSubscribeReset(reset); + break; + } + } + + private void onSubscribeBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + final OctetsFW extension = begin.extension(); + + onSubscribeBegin: + { + if (client == null) + { + doSubscribeReset(traceId, authorization); + break onSubscribeBegin; + } + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + initialMax = maximum; + state = MqttState.openingInitial(state); + + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + + assert mqttBeginEx.kind() == MqttBeginExFW.KIND_SUBSCRIBE; + final MqttSubscribeBeginExFW mqttSubscribeBeginEx = mqttBeginEx.subscribe(); + + final Array32FW filters = mqttSubscribeBeginEx.filters(); + + filters.forEach(filter -> + { + Subscription subscription = new Subscription(); + subscription.id = (int) filter.subscriptionId(); + subscription.filter = filter.pattern().asString(); + subscription.flags = filter.flags(); + subscription.qos = filter.qos(); + subscriptions.add(subscription); + }); + final int qos = subscriptions.get(0).qos; + client.subscribeStreams.put(qos, this); + + doSubscribeBegin(traceId, authorization, affinity); + doSubscribeWindow(traceId, authorization, client.encodeSlotOffset, encodeBudgetMax); + } + } + + private void onSubscribeFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + final OctetsFW extension = flush.extension(); + final MqttFlushExFW mqttFlushEx = extension.get(mqttFlushExRO::tryWrap); + + assert mqttFlushEx.kind() == MqttFlushExFW.KIND_SUBSCRIBE; + final MqttSubscribeFlushExFW mqttSubscribeFlushEx = mqttFlushEx.subscribe(); + + Array32FW filters = mqttSubscribeFlushEx.filters(); + + final List newSubscribeState = new ArrayList<>(); + filters.forEach(f -> + { + Subscription subscription = new Subscription(); + subscription.id = (int) f.subscriptionId(); + subscription.filter = f.pattern().asString(); + subscription.flags = f.flags(); + subscription.qos = f.qos(); + newSubscribeState.add(subscription); + }); + + this.subscriptions = newSubscribeState; + } + + private void doSubscribeBegin( + long traceId, + long authorization, + long affinity) + { + state = MqttState.openingReply(state); + + doBegin(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, EMPTY_OCTETS); + } + + + private void doSubscribeAbort( + long traceId, + long authorization) + { + if (!MqttState.replyClosed(state)) + { + state = MqttState.closeReply(state); + + doAbort(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void doSubscribeEnd( + long traceId, + long authorization) + { + if (!MqttState.replyClosed(state)) + { + state = MqttState.closeReply(state); + + doEnd(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void onSubscribeReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + final long authorization = reset.authorization(); + + state = MqttState.closeReply(state); + + client.doNetworkReset(traceId, authorization); + } + + private void onSubscribeWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyPad = padding; + state = MqttState.openReply(state); + + client.doNetworkWindow(traceId, authorization, padding, budgetId); + client.decodeNetwork(traceId); + } + + private void onSubscribeEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttState.closeInitial(state); + + assert initialAck <= initialSeq; + + final int packetId = client.nextPacketId(); + client.doEncodeUnsubscribe(traceId, authorization, subscriptions, packetId); + doSubscribeEnd(traceId, authorization); + } + + private void onSubscribeAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttState.closeInitial(state); + + assert initialAck <= initialSeq; + + client.doNetworkAbort(traceId, authorization); + } + + private void cleanupAbort( + long traceId, + long authorization) + { + doSubscribeAbort(traceId, authorization); + doSubscribeReset(traceId, authorization); + } + + + private void doSubscribeWindow( + long traceId, + long authorization, + int minInitialNoAck, + int minInitialMax) + { + final long newInitialAck = Math.max(initialSeq - minInitialNoAck, initialAck); + + if (newInitialAck > initialAck || minInitialMax > initialMax || !MqttState.initialOpened(state)) + { + initialAck = newInitialAck; + assert initialAck <= initialSeq; + + initialMax = minInitialMax; + + state = MqttState.openInitial(state); + + doWindow(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, client.encodeBudgetId, PUBLISH_FRAMING); + } + } + + private void doSubscribeReset( + long traceId, + long authorization) + { + if (!MqttState.initialClosed(state)) + { + state = MqttState.closeInitial(state); + + doReset(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + + private void doSubscribeData( + long traceId, + long authorization, + int reserved, + OctetsFW payload, + Flyweight extension) + { + assert MqttState.replyOpening(state); + + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + final int length = limit - offset; + assert reserved >= length + replyPad; + + doData(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, reserved, buffer, offset, length, extension); + + replySeq += reserved; + + assert replySeq <= replyAck + replyMax; + } + } + + + private class MqttPublishStream + { + private final MessageConsumer application; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private long budgetId; + + private MqttClient client; + private BudgetDebitor debitor; + private long debitorIndex = NO_DEBITOR_INDEX; + + private long initialSeq; + private long initialAck; + private int initialMax; + private int initialPad; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private int state; + + private long publishExpiresId = NO_CANCEL_ID; + private long publishExpiresAt; + private String topic; + + + MqttPublishStream( + MqttClient client, + MessageConsumer application, + long originId, + long routedId, + long initialId) + { + this.client = client; + this.application = application; + this.originId = originId; + this.routedId = routedId; + this.initialId = initialId; + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void onPublish( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onPublishBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onPublishData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onPublishEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onPublishAbort(abort); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onPublishWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onPublishReset(reset); + break; + case SignalFW.TYPE_ID: + final SignalFW signal = signalRO.wrap(buffer, index, index + length); + onPublishSignal(signal); + break; + } + } + + private void onPublishBegin( + BeginFW begin) + { + + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + final OctetsFW extension = begin.extension(); + + onPublishBegin: + { + if (client == null) + { + doPublishReset(traceId, authorization); + break onPublishBegin; + } + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + initialAck = acknowledge; + initialMax = maximum; + state = MqttState.openingInitial(state); + + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + + assert mqttBeginEx.kind() == MqttBeginExFW.KIND_PUBLISH; + final MqttPublishBeginExFW mqttPublishBeginEx = mqttBeginEx.publish(); + + this.topic = mqttPublishBeginEx.topic().asString(); + client.publishStreams.add(this); + + doPublishBegin(traceId, authorization, affinity); + doPublishWindow(traceId, authorization, client.encodeSlotOffset, encodeBudgetMax); + } + } + + private void onPublishData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final int reserved = data.reserved(); + final long authorization = data.authorization(); + final int flags = data.flags(); + final OctetsFW payload = data.payload(); + final OctetsFW extension = data.extension(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge <= initialAck; + + initialSeq = sequence + reserved; + client.encodeSharedBudget -= reserved; + + assert initialAck <= initialSeq; + + if (initialSeq > initialAck + initialMax) + { + doPublishAbort(traceId, authorization); + client.doNetworkAbort(traceId, authorization); + } + else + { + if (payload != null && payload.sizeof() <= maximumPacketSize) + { + client.doEncodePublish(traceId, authorization, flags, payload, extension, topic); + } + else + { + droppedHandler.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); + } + doPublishWindow(traceId, authorization, client.encodeSlotOffset, encodeBudgetMax); + } + } + + private void onPublishEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttState.closeInitial(state); + + assert initialAck <= initialSeq; + + doPublishEnd(traceId, authorization); + } + + private void onPublishAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= initialSeq; + + initialSeq = sequence; + state = MqttState.closeInitial(state); + + assert initialAck <= initialSeq; + + client.doNetworkAbort(traceId, authorization); + } + + private void onPublishWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + + assert acknowledge <= sequence; + assert sequence <= replySeq; + assert acknowledge >= replyAck; + assert maximum >= replyMax; + + replyAck = acknowledge; + replyMax = maximum; + replyPad = padding; + state = MqttState.openReply(state); + + client.doNetworkWindow(traceId, authorization, padding, budgetId); + } + + private void onPublishReset( + ResetFW reset) + { + final long traceId = reset.traceId(); + final long authorization = reset.authorization(); + + state = MqttState.closeReply(state); + + client.doNetworkReset(traceId, authorization); + } + + private void onPublishSignal( + SignalFW signal) + { + final int signalId = signal.signalId(); + + switch (signalId) + { + case PUBLISH_EXPIRED_SIGNAL: + onPublishExpiredSignal(signal); + break; + default: + break; + } + } + + private void onPublishExpiredSignal( + SignalFW signal) + { + final long traceId = signal.traceId(); + final long authorization = signal.authorization(); + + final long now = System.currentTimeMillis(); + if (now >= publishExpiresAt) + { + doPublishEnd(traceId, authorization); + } + else + { + publishExpiresId = NO_CANCEL_ID; + doSignalPublishExpiration(); + } + } + + + private void doPublishBegin( + long traceId, + long authorization, + long affinity) + { + state = MqttState.openingReply(state); + + doBegin(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, affinity, EMPTY_OCTETS); + } + + private void doPublishAbort( + long traceId, + long authorization) + { + if (!MqttState.replyClosed(state)) + { + state = MqttState.closeReply(state); + + doAbort(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void doSignalPublishExpiration() + { + publishExpiresAt = System.currentTimeMillis() + publishTimeoutMillis; + + if (publishExpiresId == NO_CANCEL_ID) + { + publishExpiresId = + signaler.signalAt(publishExpiresAt, originId, routedId, initialId, PUBLISH_EXPIRED_SIGNAL, 0); + } + } + + private void doCancelPublishExpiration() + { + if (publishExpiresId != NO_CANCEL_ID) + { + signaler.cancel(publishExpiresId); + publishExpiresId = NO_CANCEL_ID; + } + } + + private void doPublishWindow( + long traceId, + long authorization, + int minInitialNoAck, + int minInitialMax) + { + final long newInitialAck = Math.max(initialSeq - minInitialNoAck, initialAck); + + if (newInitialAck > initialAck || minInitialMax > initialMax || !MqttState.initialOpened(state)) + { + initialAck = newInitialAck; + assert initialAck <= initialSeq; + + initialMax = minInitialMax; + + state = MqttState.openInitial(state); + + doWindow(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, client.encodeBudgetId, PUBLISH_FRAMING); + } + } + + private void doPublishReset( + long traceId, + long authorization) + { + if (!MqttState.initialClosed(state)) + { + state = MqttState.closeInitial(state); + + doReset(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void doPublishEnd( + long traceId, + long authorization) + { + if (!MqttState.replyClosed(state)) + { + state = MqttState.closeReply(state); + + doEnd(application, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, EMPTY_OCTETS); + } + } + + private void cleanupAbort( + long traceId, + long authorization) + { + doPublishAbort(traceId, authorization); + doPublishReset(traceId, authorization); + doCancelPublishExpiration(); + } + } + + private static boolean isSetSessionExpiryInterval( + int flags) + { + return (flags & CONNACK_SESSION_EXPIRY_MASK) != 0; + } + + private static boolean isSetTopicAliasMaximum( + int flags) + { + return (flags & CONNACK_TOPIC_ALIAS_MAXIMUM_MASK) != 0; + } + + private static boolean isSetMaximumQos( + int flags) + { + return (flags & CONNACK_MAXIMUM_QOS_MASK) != 0; + } + + private static boolean isSetMaximumPacketSize( + int flags) + { + return (flags & CONNACK_MAXIMUM_PACKET_SIZE_MASK) != 0; + } + + private static boolean isSetRetainAvailable( + int flags) + { + return (flags & CONNACK_RETAIN_AVAILABLE_MASK) != 0; + } + + private static boolean isSetAssignedClientId( + int flags) + { + return (flags & CONNACK_ASSIGNED_CLIENT_IDENTIFIER_MASK) != 0; + } + + private static boolean isSetWildcardSubscriptions( + int flags) + { + return (flags & CONNACK_WILDCARD_SUBSCRIPTION_AVAILABLE_MASK) != 0; + } + + private static boolean isSetSubscriptionIdentifiers( + int flags) + { + return (flags & CONNACK_SUBSCRIPTION_IDENTIFIERS_MASK) != 0; + } + + private static boolean isSetSharedSubscriptions( + int flags) + { + return (flags & CONNACK_SHARED_SUBSCRIPTION_AVAILABLE_MASK) != 0; + } + + private static boolean isSetServerKeepAlive( + int flags) + { + return (flags & CONNACK_KEEP_ALIVE_MASK) != 0; + } + + private static boolean isSetWillFlag( + int flags) + { + return (flags & MqttSessionFlags.WILL.value() << 1) != 0; + } + + private static int decodeConnackFlags( + int flags) + { + int reasonCode = SUCCESS; + + if ((flags & CONNACK_RESERVED_FLAGS_MASK) != 0) + { + reasonCode = MALFORMED_PACKET; + } + + return reasonCode; + } + + private final class MqttPublishHeader + { + private String topic; + private int flags; + private int expiryInterval = DEFAULT_EXPIRY_INTERVAL; + private String16FW contentType = NULL_STRING; + private MqttPayloadFormat payloadFormat = DEFAULT_FORMAT; + private String16FW responseTopic = NULL_STRING; + private OctetsFW correlationData = null; + private int qos; + private boolean retained = false; + + private MqttPublishHeader reset() + { + this.topic = null; + this.flags = 0; + this.expiryInterval = DEFAULT_EXPIRY_INTERVAL; + this.contentType = NULL_STRING; + this.payloadFormat = DEFAULT_FORMAT; + this.responseTopic = NULL_STRING; + this.correlationData = null; + + return this; + } + + private int decode( + MqttClient client, + String16FW topicName, + MqttPropertiesFW properties, + int typeAndFlags) + { + this.topic = topicName.asString(); + int reasonCode = SUCCESS; + userPropertiesRW.wrap(userPropertiesBuffer, 0, userPropertiesBuffer.capacity()); + subscriptionIdsRW.wrap(subscriptionIdsBuffer, 0, subscriptionIdsBuffer.capacity()); + + final OctetsFW propertiesValue = properties.value(); + final DirectBuffer decodeBuffer = propertiesValue.buffer(); + final int decodeOffset = propertiesValue.offset(); + final int decodeLimit = propertiesValue.limit(); + + if (topic == null) + { + reasonCode = PROTOCOL_ERROR; + } + else + { + flags = calculatePublishFlags(typeAndFlags); + qos = calculatePublishQos(typeAndFlags); + + int alias = 0; + if (qos > client.maximumQos) + { + reasonCode = QOS_NOT_SUPPORTED; + } + else if (retained && !isRetainAvailable(client.capabilities)) + { + reasonCode = RETAIN_NOT_SUPPORTED; + } + else + { + decode: + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + { + final MqttPropertyFW mqttProperty = mqttPropertyRO.wrap(decodeBuffer, decodeProgress, decodeLimit); + switch (mqttProperty.kind()) + { + case KIND_EXPIRY_INTERVAL: + expiryInterval = mqttProperty.expiryInterval(); + break; + case KIND_CONTENT_TYPE: + final String16FW mContentType = mqttProperty.contentType(); + if (mContentType.value() != null) + { + final int offset = mContentType.offset(); + final int limit = mContentType.limit(); + + contentType = contentTypeRO.wrap(mContentType.buffer(), offset, limit); + } + break; + case KIND_TOPIC_ALIAS: + if (alias != 0) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + + alias = mqttProperty.topicAlias() & 0xFFFF; + + if (alias <= 0 || alias > client.topicAliasMaximum) + { + reasonCode = TOPIC_ALIAS_INVALID; + break decode; + } + + if (topic.isEmpty()) + { + if (!client.topicAliases.containsKey(alias)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + topic = client.topicAliases.get(alias); + } + else + { + client.topicAliases.put(alias, topic); + } + break; + case KIND_SUBSCRIPTION_ID: + subscriptionIdsRW.item(i -> i.set(mqttProperty.subscriptionId().value())); + break; + case KIND_PAYLOAD_FORMAT: + payloadFormat = MqttPayloadFormat.valueOf(mqttProperty.payloadFormat()); + break; + case KIND_RESPONSE_TOPIC: + final String16FW mResponseTopic = mqttProperty.responseTopic(); + if (mResponseTopic.value() != null) + { + final int offset = mResponseTopic.offset(); + final int limit = mResponseTopic.limit(); + + responseTopic = responseTopicRO.wrap(mResponseTopic.buffer(), offset, limit); + } + break; + case KIND_CORRELATION_DATA: + correlationData = mqttProperty.correlationData().bytes(); + break; + case KIND_USER_PROPERTY: + final MqttUserPropertyFW userProperty = mqttProperty.userProperty(); + userPropertiesRW.item(c -> c.key(userProperty.key()).value(userProperty.value())); + break; + default: + reasonCode = MALFORMED_PACKET; + break decode; + } + decodeProgress = mqttProperty.limit(); + } + } + } + + return reasonCode; + } + private int calculatePublishQos( + int networkTypeAndFlags) + { + int qos = 0; + if ((networkTypeAndFlags & PUBLISH_QOS1_MASK) != 0) + { + qos = 1; + } + else if ((networkTypeAndFlags & PUBLISH_QOS2_MASK) != 0) + { + qos = 2; + } + return qos; + } + + private int calculatePublishFlags( + int networkTypeAndFlags) + { + int flags = 0; + + if ((networkTypeAndFlags & RETAIN_MASK) != 0) + { + flags |= RETAIN_FLAG; + retained = true; + } + return flags; + } + } + + private boolean isRetainAvailable( + int capabilities) + { + return (capabilities & 1 << MqttServerCapabilities.RETAIN.value()) != 0; + } + + private final class Subscription + { + private int id = 0; + private String filter; + private int qos; + private int flags; + private int reasonCode; + + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + if (!(obj instanceof Subscription)) + { + return false; + } + Subscription other = (Subscription) obj; + return this.id == other.id && Objects.equals(this.filter, other.filter) && + this.qos == other.qos && this.flags == other.flags && this.reasonCode == other.reasonCode; + } + + @Override + public int hashCode() + { + return Objects.hash(this.id, this.filter, this.qos, this.flags, this.reasonCode); + } + } +} + diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java similarity index 79% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java index 23a2c254ea..af7670f022 100644 --- a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java @@ -16,16 +16,20 @@ package io.aklivity.zilla.runtime.binding.mqtt.internal.stream; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.BAD_AUTHENTICATION_METHOD; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.BAD_USER_NAME_OR_PASSWORD; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.CLIENT_IDENTIFIER_NOT_VALID; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.DISCONNECT_WITH_WILL_MESSAGE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.GRANTED_QOS_2; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.KEEP_ALIVE_TIMEOUT; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.MALFORMED_PACKET; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.NORMAL_DISCONNECT; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.NO_SUBSCRIPTION_EXISTED; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.PACKET_TOO_LARGE; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.PAYLOAD_FORMAT_INVALID; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.PROTOCOL_ERROR; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.QOS_NOT_SUPPORTED; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.RETAIN_NOT_SUPPORTED; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.SERVER_MOVED; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.SESSION_TAKEN_OVER; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.SHARED_SUBSCRIPTION_NOT_SUPPORTED; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttReasonCodes.SUBSCRIPTION_IDS_NOT_SUPPORTED; @@ -81,37 +85,39 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.IntSupplier; import java.util.function.LongFunction; import java.util.function.LongSupplier; import java.util.function.LongUnaryOperator; import java.util.function.Supplier; +import java.util.function.ToLongFunction; import java.util.stream.Collectors; -import jakarta.json.Json; -import jakarta.json.JsonBuilderFactory; - import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; +import org.agrona.collections.Int2IntHashMap; import org.agrona.collections.Int2ObjectHashMap; import org.agrona.collections.Long2ObjectHashMap; import org.agrona.collections.MutableBoolean; +import org.agrona.collections.Object2IntHashMap; import org.agrona.concurrent.UnsafeBuffer; import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttBinding; import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration; import io.aklivity.zilla.runtime.binding.mqtt.internal.MqttValidator; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttConnectProperty; import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttBindingConfig; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttOptionsConfig; import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttRouteConfig; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttBinaryFW; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttCapabilities; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttEndReasonCode; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttMessageFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttPayloadFormat; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttPayloadFormatFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttQoS; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttSessionStateFW; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttTopicFilterFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.MqttWillMessageFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.OctetsFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.Varuint32FW; @@ -142,9 +148,11 @@ import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.FlushFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttDataExFW; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttEndExFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttFlushExFW; -import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttPublishDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttResetExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttServerCapabilities; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttSessionBeginExFW; +import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.MqttSessionDataKind; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.ResetFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.SignalFW; import io.aklivity.zilla.runtime.binding.mqtt.internal.types.stream.WindowFW; @@ -156,6 +164,7 @@ import io.aklivity.zilla.runtime.engine.buffer.BufferPool; import io.aklivity.zilla.runtime.engine.concurrent.Signaler; import io.aklivity.zilla.runtime.engine.config.BindingConfig; +import io.aklivity.zilla.runtime.engine.guard.GuardHandler; public final class MqttServerFactory implements MqttStreamFactory { @@ -177,7 +186,10 @@ public final class MqttServerFactory implements MqttStreamFactory private static final int NO_LOCAL_FLAG_MASK = 0b0000_0100; private static final int RETAIN_AS_PUBLISHED_MASK = 0b0000_1000; private static final int RETAIN_HANDLING_MASK = 0b0011_0000; - private static final int BASIC_AUTHENTICATION_MASK = 0b1100_0000; + private static final int RETAIN_AVAILABLE_MASK = 1 << MqttServerCapabilities.RETAIN.value(); + private static final int WILDCARD_AVAILABLE_MASK = 1 << MqttServerCapabilities.WILDCARD.value(); + private static final int SUBSCRIPTION_IDS_AVAILABLE_MASK = 1 << MqttServerCapabilities.SUBSCRIPTION_IDS.value(); + private static final int SHARED_SUBSCRIPTIONS_AVAILABLE_MASK = 1 << MqttServerCapabilities.SHARED_SUBSCRIPTIONS.value(); private static final int WILL_FLAG_MASK = 0b0000_0100; private static final int CLEAN_START_FLAG_MASK = 0b0000_0010; @@ -211,8 +223,7 @@ public final class MqttServerFactory implements MqttStreamFactory private static final String16FW NULL_STRING = new String16FW((String) null); public static final String SHARED_SUBSCRIPTION_LITERAL = "$share"; - - private final JsonBuilderFactory json = Json.createBuilderFactory(new HashMap<>()); + public static final int GENERATED_SUBSCRIPTION_ID_MASK = 0x70; private final BeginFW beginRO = new BeginFW(); private final DataFW dataRO = new DataFW(); @@ -230,18 +241,17 @@ public final class MqttServerFactory implements MqttStreamFactory private final ResetFW.Builder resetRW = new ResetFW.Builder(); private final FlushFW.Builder flushRW = new FlushFW.Builder(); - private final MqttPublishDataExFW mqttPublishDataExRO = new MqttPublishDataExFW(); private final MqttDataExFW mqttSubscribeDataExRO = new MqttDataExFW(); + private final MqttResetExFW mqttResetExRO = new MqttResetExFW(); + private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); private final MqttBeginExFW.Builder mqttPublishBeginExRW = new MqttBeginExFW.Builder(); private final MqttBeginExFW.Builder mqttSubscribeBeginExRW = new MqttBeginExFW.Builder(); private final MqttBeginExFW.Builder mqttSessionBeginExRW = new MqttBeginExFW.Builder(); - private final MqttEndExFW.Builder mqttEndExRW = new MqttEndExFW.Builder(); private final MqttDataExFW.Builder mqttPublishDataExRW = new MqttDataExFW.Builder(); - private final MqttDataExFW.Builder mqttSubscribeDataExRW = new MqttDataExFW.Builder(); private final MqttDataExFW.Builder mqttSessionDataExRW = new MqttDataExFW.Builder(); private final MqttFlushExFW.Builder mqttFlushExRW = new MqttFlushExFW.Builder(); - private final MqttMessageFW.Builder mqttMessageFW = new MqttMessageFW.Builder(); + private final MqttWillMessageFW.Builder mqttWillMessageRW = new MqttWillMessageFW.Builder(); private final MqttSessionStateFW.Builder mqttSessionStateFW = new MqttSessionStateFW.Builder(); private final MqttPacketHeaderFW mqttPacketHeaderRO = new MqttPacketHeaderFW(); private final MqttConnectFW mqttConnectRO = new MqttConnectFW(); @@ -261,20 +271,11 @@ public final class MqttServerFactory implements MqttStreamFactory private final MqttPropertyFW mqttPropertyRO = new MqttPropertyFW(); private final MqttPropertyFW.Builder mqttPropertyRW = new MqttPropertyFW.Builder(); - private final MqttPropertiesFW mqttPropertiesRO = new MqttPropertiesFW(); private final MqttSessionStateFW mqttSessionStateRO = new MqttSessionStateFW(); - private final String16FW.Builder clientIdRW = new String16FW.Builder(BIG_ENDIAN); - - private final String16FW clientIdRO = new String16FW(BIG_ENDIAN); private final String16FW contentTypeRO = new String16FW(BIG_ENDIAN); private final String16FW responseTopicRO = new String16FW(BIG_ENDIAN); - private final String16FW willTopicRO = new String16FW(BIG_ENDIAN); private final String16FW usernameRO = new String16FW(BIG_ENDIAN); - - private final OctetsFW.Builder sessionPayloadRW = new OctetsFW.Builder(); - - private final BinaryFW willPayloadRO = new BinaryFW(); private final BinaryFW passwordRO = new BinaryFW(); private final MqttPublishHeader mqttPublishHeaderRO = new MqttPublishHeader(); @@ -289,15 +290,13 @@ public final class MqttServerFactory implements MqttStreamFactory private final MqttDisconnectFW.Builder mqttDisconnectRW = new MqttDisconnectFW.Builder(); private final Array32FW.Builder userPropertiesRW = new Array32FW.Builder<>(new MqttUserPropertyFW.Builder(), new MqttUserPropertyFW()); - - private final Array32FW.Builder topicFiltersRW = - new Array32FW.Builder<>(new MqttTopicFilterFW.Builder(), new MqttTopicFilterFW()); private final Array32FW.Builder willUserPropertiesRW = new Array32FW.Builder<>(new MqttUserPropertyFW.Builder(), new MqttUserPropertyFW()); private final MqttServerDecoder decodeInitialType = this::decodeInitialType; private final MqttServerDecoder decodePacketType = this::decodePacketType; private final MqttServerDecoder decodeConnect = this::decodeConnect; + private final MqttServerDecoder decodeConnectPayload = this::decodeConnectPayload; private final MqttServerDecoder decodePublish = this::decodePublish; private final MqttServerDecoder decodeSubscribe = this::decodeSubscribe; private final MqttServerDecoder decodeUnsubscribe = this::decodeUnsubscribe; @@ -307,7 +306,8 @@ public final class MqttServerFactory implements MqttStreamFactory private final MqttServerDecoder decodeUnknownType = this::decodeUnknownType; private final Map decodersByPacketType; - private final boolean session; + private final IntSupplier supplySubscriptionId; + private int maximumPacketSize; { final Map decodersByPacketType = new EnumMap<>(MqttPacketType.class); @@ -327,16 +327,15 @@ public final class MqttServerFactory implements MqttStreamFactory private final MutableDirectBuffer writeBuffer; private final MutableDirectBuffer extBuffer; private final MutableDirectBuffer dataExtBuffer; - private final MutableDirectBuffer clientIdBuffer; - private final MutableDirectBuffer willDataExtBuffer; private final MutableDirectBuffer payloadBuffer; private final MutableDirectBuffer propertyBuffer; private final MutableDirectBuffer sessionExtBuffer; private final MutableDirectBuffer sessionStateBuffer; private final MutableDirectBuffer userPropertiesBuffer; private final MutableDirectBuffer willMessageBuffer; - private final MutableDirectBuffer willPropertyBuffer; private final MutableDirectBuffer willUserPropertiesBuffer; + + private final ByteBuffer charsetBuffer; private final BufferPool bufferPool; private final BudgetCreditor creditor; private final Signaler signaler; @@ -347,6 +346,7 @@ public final class MqttServerFactory implements MqttStreamFactory private final LongSupplier supplyTraceId; private final LongSupplier supplyBudgetId; private final LongFunction supplyDebitor; + private final LongFunction supplyGuard; private final Long2ObjectHashMap bindings; private final int mqttTypeId; @@ -354,15 +354,9 @@ public final class MqttServerFactory implements MqttStreamFactory private final long connectTimeoutMillis; private final int encodeBudgetMax; - private final int sessionExpiryIntervalLimit; private final short keepAliveMinimum; private final short keepAliveMaximum; - private final byte maximumQos; - private final byte retainedMessages; private final short topicAliasMaximumLimit; - private final byte wildcardSubscriptions; - private final byte subscriptionIdentifiers; - private final byte sharedSubscriptions; private final boolean noLocal; private final int sessionExpiryGracePeriod; private final Supplier supplyClientId; @@ -378,15 +372,13 @@ public MqttServerFactory( this.writeBuffer = context.writeBuffer(); this.extBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.dataExtBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); - this.clientIdBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); - this.willDataExtBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.propertyBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.userPropertiesBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); + this.charsetBuffer = ByteBuffer.wrap(new byte[writeBuffer.capacity()]); this.payloadBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.sessionExtBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.sessionStateBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.willMessageBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); - this.willPropertyBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.willUserPropertiesBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); this.bufferPool = context.bufferPool(); this.creditor = context.creditor(); @@ -398,25 +390,21 @@ public MqttServerFactory( this.supplyReplyId = context::supplyReplyId; this.supplyBudgetId = context::supplyBudgetId; this.supplyTraceId = context::supplyTraceId; + this.supplyGuard = context::supplyGuard; this.bindings = new Long2ObjectHashMap<>(); this.mqttTypeId = context.supplyTypeId(MqttBinding.NAME); this.publishTimeoutMillis = SECONDS.toMillis(config.publishTimeout()); this.connectTimeoutMillis = SECONDS.toMillis(config.connectTimeout()); - this.sessionExpiryIntervalLimit = config.sessionExpiryInterval(); this.keepAliveMinimum = config.keepAliveMinimum(); this.keepAliveMaximum = config.keepAliveMaximum(); - this.maximumQos = config.maximumQos(); - this.retainedMessages = config.retainAvailable() ? (byte) 1 : 0; - this.wildcardSubscriptions = config.wildcardSubscriptionAvailable() ? (byte) 1 : 0; - this.subscriptionIdentifiers = config.subscriptionIdentifierAvailable() ? (byte) 1 : 0; - this.sharedSubscriptions = config.sharedSubscriptionAvailable() ? (byte) 1 : 0; - this.session = config.sessionsAvailable(); + this.maximumPacketSize = writeBuffer.capacity(); this.topicAliasMaximumLimit = (short) Math.max(config.topicAliasMaximum(), 0); this.noLocal = config.noLocal(); this.sessionExpiryGracePeriod = config.sessionExpiryGracePeriod(); this.encodeBudgetMax = bufferPool.slotCapacity(); this.validator = new MqttValidator(); this.utf8Decoder = StandardCharsets.UTF_8.newDecoder(); + this.supplySubscriptionId = config.subscriptionId(); final Optional clientId = Optional.ofNullable(config.clientId()).map(String16FW::new); this.supplyClientId = clientId.isPresent() ? clientId::get : () -> new String16FW(UUID.randomUUID().toString()); @@ -461,6 +449,10 @@ public MessageConsumer newStream( final long budgetId = supplyBudgetId.getAsLong(); newStream = new MqttServer( + binding.credentials(), + binding.authField(), + binding.options, + binding.resolveId, sender, originId, routedId, @@ -478,13 +470,6 @@ private int topicKey( return System.identityHashCode(topic.intern()); } - private int subscribeKey( - String clientId, - long resolveId) - { - return System.identityHashCode((clientId + "_" + resolveId).intern()); - } - private MessageConsumer newStream( MessageConsumer sender, long originId, @@ -583,43 +568,6 @@ private void doData( receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); } - private void doData( - MessageConsumer receiver, - long originId, - long routedId, - long streamId, - long sequence, - long acknowledge, - int maximum, - long traceId, - long authorization, - long budgetId, - int reserved, - int flags, - DirectBuffer buffer, - int index, - int length, - Flyweight extension) - { - final DataFW data = dataRW.wrap(writeBuffer, 0, writeBuffer.capacity()) - .originId(originId) - .routedId(routedId) - .streamId(streamId) - .sequence(sequence) - .acknowledge(acknowledge) - .maximum(maximum) - .traceId(traceId) - .authorization(authorization) - .flags(flags) - .budgetId(budgetId) - .reserved(reserved) - .payload(buffer, index, length) - .extension(extension.buffer(), extension.offset(), extension.sizeof()) - .build(); - - receiver.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); - } - private void doEnd( MessageConsumer receiver, long originId, @@ -785,11 +733,8 @@ private int decodeInitialType( break decode; } - if (limit - packet.limit() >= length) - { - server.decodeablePacketBytes = packet.sizeof() + length; - server.decoder = decodePacketType; - } + server.decodeablePacketBytes = packet.sizeof() + length; + server.decoder = decodePacketType; } return offset; @@ -812,7 +757,12 @@ private int decodePacketType( final MqttPacketType packetType = MqttPacketType.valueOf(packet.typeAndFlags() >> 4); final MqttServerDecoder decoder = decodersByPacketType.getOrDefault(packetType, decodeUnknownType); - if (limit - packet.limit() >= length) + if (packet.sizeof() + length > maximumPacketSize) + { + server.onDecodeError(traceId, authorization, PACKET_TOO_LARGE); + server.decoder = decodeIgnoreAll; + } + else if (limit - packet.limit() >= length) { server.decodeablePacketBytes = packet.sizeof() + length; server.decoder = decoder; @@ -840,6 +790,7 @@ private int decodeConnect( int reasonCode = SUCCESS; final MqttConnectFW mqttConnect = mqttConnectRO.tryWrap(buffer, offset, limit); + int flags = 0; decode: { if (mqttConnect == null) @@ -848,7 +799,8 @@ private int decodeConnect( break decode; } - int flags = mqttConnect.flags(); + server.decodableRemainingBytes = mqttConnect.remainingLength(); + flags = mqttConnect.flags(); reasonCode = decodeConnectType(mqttConnect, flags); if (reasonCode != SUCCESS) @@ -868,7 +820,31 @@ private int decodeConnect( break decode; } + if (server.connected) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + + if (mqttConnect.clientId().length() > MAXIMUM_CLIENT_ID_LENGTH) + { + reasonCode = CLIENT_IDENTIFIER_NOT_VALID; + break decode; + } + + final MqttPropertiesFW properties = mqttConnect.properties(); + + reasonCode = server.decodeConnectProperties(properties); + + if (reasonCode != SUCCESS) + { + break decode; + } + progress = server.onDecodeConnect(traceId, authorization, buffer, progress, limit, mqttConnect); + + final int decodedLength = progress - offset - 2; + server.decodableRemainingBytes -= decodedLength; } if (reasonCode != SUCCESS) @@ -876,6 +852,31 @@ private int decodeConnect( server.onDecodeError(traceId, authorization, reasonCode); server.decoder = decodeIgnoreAll; } + else + { + server.decoder = decodeConnectPayload; + } + } + + return progress; + } + + private int decodeConnectPayload( + MqttServer server, + final long traceId, + final long authorization, + final long budgetId, + final DirectBuffer buffer, + final int offset, + final int limit) + { + int progress = offset; + + progress = server.onDecodeConnectPayload(traceId, authorization, buffer, progress, limit); + server.decodableRemainingBytes -= progress - offset; + if (server.decodableRemainingBytes == 0) + { + server.decoder = decodePacketType; } return progress; @@ -971,18 +972,22 @@ private int decodePublish( return progress; } - private boolean invalidUtf8(OctetsFW payload) + private boolean invalidUtf8( + OctetsFW payload) { boolean invalid = false; - byte[] payloadBytes = new byte[payload.sizeof()]; - payload.value().getBytes(0, payloadBytes); + byte[] payloadBytes = charsetBuffer.array(); + final int payloadSize = payload.sizeof(); + payload.value().getBytes(0, payloadBytes, 0, payloadSize); try { - utf8Decoder.decode(ByteBuffer.wrap(payloadBytes)); + charsetBuffer.position(0).limit(payloadSize); + utf8Decoder.decode(charsetBuffer); } catch (CharacterCodingException ex) { invalid = true; + utf8Decoder.reset(); } return invalid; } @@ -1000,6 +1005,7 @@ private int decodeSubscribe( int progress = offset; + decode: if (length > 0) { int reasonCode = SUCCESS; @@ -1016,6 +1022,11 @@ else if ((subscribe.typeAndFlags() & 0b1111_1111) != SUBSCRIBE_FIXED_HEADER) if (reasonCode == 0) { + if (!MqttState.replyOpened(server.sessionStream.state)) + { + //We don't know the server capabilities yet + break decode; + } server.onDecodeSubscribe(traceId, authorization, subscribe); server.decoder = decodePacketType; progress = subscribe.limit(); @@ -1119,10 +1130,20 @@ private int decodeDisconnect( int progress = offset; + decode: if (length > 0) { int reasonCode = NORMAL_DISCONNECT; + + if (limit - offset == 2) + { + server.onDecodeDisconnect(traceId, authorization, null); + progress = limit; + server.decoder = decodePacketType; + break decode; + } + final MqttDisconnectFW disconnect = mqttDisconnectRO.tryWrap(buffer, offset, limit); if (disconnect == null) { @@ -1195,19 +1216,22 @@ private final class MqttServer private final long routedId; private final long initialId; private final long replyId; - private final long affinity; private final long encodeBudgetId; private final Int2ObjectHashMap publishStreams; - private final Int2ObjectHashMap subscribeStreams; + private final Long2ObjectHashMap subscribeStreams; private final Int2ObjectHashMap topicAliases; - private final Map subscribePacketIds; - private final Map unsubscribePacketIds; + private final Int2IntHashMap subscribePacketIds; + private final Object2IntHashMap unsubscribePacketIds; + private final GuardHandler guard; + private final Function credentials; + private final MqttConnectProperty authField; private MqttSessionStream sessionStream; private String16FW clientId; + private long affinity; private long decodeSeq; private long decodeAck; private int decodeMax; @@ -1238,21 +1262,30 @@ private final class MqttServer private long keepAliveTimeoutId = NO_CANCEL_ID; private long keepAliveTimeoutAt; + private int maximumQos; + private int packetSizeMax; + private int capabilities = RETAIN_AVAILABLE_MASK | SUBSCRIPTION_IDS_AVAILABLE_MASK | WILDCARD_AVAILABLE_MASK; private boolean serverDefinedKeepAlive = false; - private boolean cleanStart = false; private short keepAlive; private long keepAliveTimeout; + private int connectFlags; private boolean connected; private short topicAliasMaximum = 0; - private int maximumPacketSize = Integer.MAX_VALUE; - private int sessionExpiryInterval = 0; + private int connectSessionExpiry = 0; + private int sessionExpiry; private boolean assignedClientId = false; - private int propertyMask = 0; + private int decodablePropertyMask = 0; private int state; + private long sessionId; + private int decodableRemainingBytes; private MqttServer( + Function credentials, + MqttConnectProperty authField, + MqttOptionsConfig options, + ToLongFunction resolveId, MessageConsumer network, long originId, long routedId, @@ -1266,14 +1299,16 @@ private MqttServer( this.routedId = routedId; this.initialId = initialId; this.replyId = replyId; - this.affinity = affinity; this.encodeBudgetId = budgetId; this.decoder = decodeInitialType; this.publishStreams = new Int2ObjectHashMap<>(); - this.subscribeStreams = new Int2ObjectHashMap<>(); + this.subscribeStreams = new Long2ObjectHashMap<>(); this.topicAliases = new Int2ObjectHashMap<>(); - this.subscribePacketIds = new HashMap<>(); - this.unsubscribePacketIds = new HashMap<>(); + this.subscribePacketIds = new Int2IntHashMap(-1); + this.unsubscribePacketIds = new Object2IntHashMap<>(-1); + this.guard = resolveGuard(options, resolveId); + this.credentials = credentials; + this.authField = authField; } private void onNetwork( @@ -1322,8 +1357,10 @@ private void onNetworkBegin( { final long traceId = begin.traceId(); final long authorization = begin.authorization(); + final long streamId = begin.streamId(); state = MqttState.openingInitial(state); + affinity = streamId; doNetworkBegin(traceId, authorization); doNetworkWindow(traceId, authorization, 0, 0L, 0, bufferPool.slotCapacity()); @@ -1387,7 +1424,7 @@ private void onNetworkEnd( { state = MqttState.closeInitial(state); - cleanupStreamsUsingAbort(traceId, authorization); + cleanupStreamsUsingAbort(traceId); doNetworkEnd(traceId, authorization); @@ -1494,13 +1531,7 @@ private void onKeepAliveTimeoutSignal( final long now = System.currentTimeMillis(); if (now >= keepAliveTimeoutAt) { - if (session) - { - final MqttEndExFW.Builder builder = mqttEndExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) - .typeId(mqttTypeId) - .reasonCode(r -> r.set(MqttEndReasonCode.KEEP_ALIVE_EXPIRY)); - sessionStream.doSessionAppEnd(traceId, authorization, builder.build()); - } + sessionStream.doSessionAbort(traceId); onDecodeError(traceId, authorization, KEEP_ALIVE_TIMEOUT); decoder = decodeIgnoreAll; } @@ -1520,7 +1551,7 @@ private void onConnectTimeoutSignal( final long now = System.currentTimeMillis(); if (now >= connectTimeoutAt) { - cleanupStreamsUsingAbort(traceId, authorization); + cleanupStreamsUsingAbort(traceId); doNetworkEnd(traceId, authorization); decoder = decodeIgnoreAll; } @@ -1552,37 +1583,38 @@ private byte decodeConnectProperties( switch (mqttProperty.kind()) { case KIND_TOPIC_ALIAS_MAXIMUM: - if (isSetTopicAliasMaximum(propertyMask)) + if (isSetTopicAliasMaximum(decodablePropertyMask)) { topicAliasMaximum = 0; reasonCode = PROTOCOL_ERROR; break decode; } - this.propertyMask |= CONNECT_TOPIC_ALIAS_MAXIMUM_MASK; + this.decodablePropertyMask |= CONNECT_TOPIC_ALIAS_MAXIMUM_MASK; final short topicAliasMaximum = (short) (mqttProperty.topicAliasMaximum() & 0xFFFF); this.topicAliasMaximum = (short) Math.min(topicAliasMaximum, topicAliasMaximumLimit); break; case KIND_SESSION_EXPIRY: - if (isSetSessionExpiryInterval(propertyMask)) + if (isSetSessionExpiryInterval(decodablePropertyMask)) { - sessionExpiryInterval = 0; + connectSessionExpiry = 0; reasonCode = PROTOCOL_ERROR; break decode; } - this.propertyMask |= CONNECT_SESSION_EXPIRY_INTERVAL_MASK; - final int sessionExpiryInterval = (int) mqttProperty.sessionExpiry(); - this.sessionExpiryInterval = Math.min(sessionExpiryInterval, sessionExpiryIntervalLimit); + this.decodablePropertyMask |= CONNECT_SESSION_EXPIRY_INTERVAL_MASK; + this.connectSessionExpiry = (int) mqttProperty.sessionExpiry(); + this.sessionExpiry = connectSessionExpiry; break; case KIND_RECEIVE_MAXIMUM: case KIND_MAXIMUM_PACKET_SIZE: - final int maximumPacketSize = (int) mqttProperty.maximumPacketSize(); - if (maximumPacketSize == 0 || isSetMaximumPacketSize(propertyMask)) + final int maxConnectPacketSize = (int) mqttProperty.maximumPacketSize(); + if (maxConnectPacketSize == 0 || isSetMaximumPacketSize(decodablePropertyMask)) { reasonCode = PROTOCOL_ERROR; break decode; } - this.propertyMask |= CONNECT_TOPIC_ALIAS_MAXIMUM_MASK; - this.maximumPacketSize = maximumPacketSize; + this.decodablePropertyMask |= CONNECT_TOPIC_ALIAS_MAXIMUM_MASK; + //TODO: remove this once we will support large messages + maximumPacketSize = Math.min(maxConnectPacketSize, maximumPacketSize); break; case KIND_REQUEST_RESPONSE_INFORMATION: case KIND_REQUEST_PROBLEM_INFORMATION: @@ -1616,138 +1648,197 @@ private int onDecodeConnect( { final String16FW clientIdentifier = connect.clientId(); this.assignedClientId = false; - byte reasonCode; + + final int length = clientIdentifier.length(); + + if (length == 0) + { + this.clientId = supplyClientId.get(); + this.assignedClientId = true; + } + else + { + this.clientId = new String16FW(clientIdentifier.asString()); + } + + keepAlive = (short) Math.min(Math.max(connect.keepAlive(), keepAliveMinimum), keepAliveMaximum); + serverDefinedKeepAlive = keepAlive != connect.keepAlive(); + keepAliveTimeout = Math.round(TimeUnit.SECONDS.toMillis(keepAlive) * 1.5); + connectFlags = connect.flags(); + doSignalKeepAliveTimeout(); + doCancelConnectTimeout(); + + progress = connect.limit(); + + return progress; + } + + private int onDecodeConnectPayload( + long traceId, + long authorization, + DirectBuffer buffer, + int progress, + int limit) + { + byte reasonCode = SUCCESS; decode: { - if (connected) + final MqttConnectPayload payload = mqttConnectPayloadRO.reset(); + int connectPayloadLimit = payload.decode(buffer, progress, limit, connectFlags); + + final boolean willFlagSet = isSetWillFlag(connectFlags); + + reasonCode = payload.reasonCode; + + if (reasonCode != SUCCESS) { - reasonCode = PROTOCOL_ERROR; break decode; } - final int length = clientIdentifier.length(); - - if (length == 0) + long sessionAuth = authorization; + if (guard != null) { - this.clientId = supplyClientId.get(); - this.assignedClientId = true; + String authField = null; + if (this.authField.equals(MqttConnectProperty.USERNAME)) + { + authField = payload.username != null ? payload.username.asString() : null; + } + else if (this.authField.equals(MqttConnectProperty.PASSWORD)) + { + authField = payload.password != null ? + payload.password.bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)) : null; + } + + final String credentialsMatch = credentials.apply(authField); + + if (credentialsMatch != null) + { + sessionAuth = guard.reauthorize(initialId, credentialsMatch); + } } - else if (length > MAXIMUM_CLIENT_ID_LENGTH) + + final MqttBindingConfig binding = bindings.get(routedId); + + final MqttRouteConfig resolved = binding != null ? + binding.resolveSession(sessionAuth, clientId.asString()) : null; + + if (resolved == null) { - reasonCode = CLIENT_IDENTIFIER_NOT_VALID; + reasonCode = BAD_USER_NAME_OR_PASSWORD; break decode; } else { - this.clientId = new String16FW(clientIdentifier.asString()); + resolveSession(traceId, resolved.id); } - final MqttPropertiesFW properties = connect.properties(); - - reasonCode = decodeConnectProperties(properties); - - if (reasonCode != SUCCESS) + if (willFlagSet && !MqttState.initialOpened(sessionStream.state)) { break decode; } - final MqttConnectPayload payload = mqttConnectPayloadRO.reset(); - progress = connect.limit(); - progress = payload.decode(buffer, progress, limit, connect.flags()); - reasonCode = payload.reasonCode; - if (reasonCode != SUCCESS) - { - break decode; - } - if (isCleanStart(connect.flags())) + if (isSetWillRetain(connectFlags)) { - this.cleanStart = true; + if (!retainAvailable(capabilities)) + { + reasonCode = RETAIN_NOT_SUPPORTED; + break decode; + } + payload.willRetain = (byte) RETAIN_FLAG; } - keepAlive = (short) Math.min(Math.max(connect.keepAlive(), keepAliveMinimum), keepAliveMaximum); - serverDefinedKeepAlive = keepAlive != connect.keepAlive(); - keepAliveTimeout = Math.round(TimeUnit.SECONDS.toMillis(keepAlive) * 1.5); - doSignalKeepAliveTimeout(); - if (session) + + if (payload.willQos > maximumQos) { - resolveSession(traceId, authorization, reasonCode, connect, payload); + reasonCode = QOS_NOT_SUPPORTED; + break decode; } - else + + this.sessionId = sessionAuth; + + final int flags = connectFlags; + final int willFlags = decodeWillFlags(flags); + final int willQos = decodeWillQos(flags); + + if (willFlagSet) { - doEncodeConnack(traceId, authorization, reasonCode, assignedClientId, false); - connected = true; - } + final MqttDataExFW.Builder sessionDataExBuilder = + mqttSessionDataExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(s -> s.kind(k -> k.set(MqttSessionDataKind.WILL))); - doCancelConnectTimeout(); + final MqttWillMessageFW.Builder willMessageBuilder = + mqttWillMessageRW.wrap(willMessageBuffer, 0, willMessageBuffer.capacity()) + .topic(payload.willTopic) + .delay(payload.willDelay) + .qos(willQos) + .flags(willFlags) + .expiryInterval(payload.expiryInterval) + .contentType(payload.contentType) + .format(f -> f.set(payload.payloadFormat)) + .responseTopic(payload.responseTopic) + .correlation(c -> c.bytes(payload.correlationData)); + + final Array32FW userProperties = willUserPropertiesRW.build(); + userProperties.forEach( + c -> willMessageBuilder.propertiesItem(p -> p.key(c.key()).value(c.value()))); + willMessageBuilder.payload(p -> p.bytes(payload.willPayload.bytes())); - decoder = decodePacketType; + final MqttWillMessageFW will = willMessageBuilder.build(); + final int willPayloadSize = willMessageBuilder.sizeof(); + + if (!sessionStream.hasSessionWindow(willPayloadSize)) + { + break decode; + } + sessionStream.doSessionData(traceId, willPayloadSize, sessionDataExBuilder.build(), will); + } + progress = connectPayloadLimit; } if (reasonCode != SUCCESS) { doCancelConnectTimeout(); - doEncodeConnack(traceId, authorization, reasonCode, assignedClientId, false); + + if (reasonCode != BAD_USER_NAME_OR_PASSWORD) + { + doEncodeConnack(traceId, authorization, reasonCode, assignedClientId, false, null); + } + + if (sessionStream != null) + { + sessionStream.doSessionAppEnd(traceId, EMPTY_OCTETS); + } doNetworkEnd(traceId, authorization); + decoder = decodeIgnoreAll; - progress = connect.limit(); + progress = limit; } + + return progress; } private void resolveSession( long traceId, - long authorization, - int reasonCode, - MqttConnectFW connect, - MqttConnectPayload payload) + long resolvedId) { - final int flags = connect.flags(); - final MqttBindingConfig binding = bindings.get(routedId); - final MqttRouteConfig resolved = binding != null ? binding.resolve(authorization, MqttCapabilities.SESSION) : null; - - if (resolved != null) - { - final long resolvedId = resolved.id; - - final boolean willFlagSet = isSetWillFlag(flags); + final int flags = connectFlags & (CLEAN_START_FLAG_MASK | WILL_FLAG_MASK); - final MqttBeginExFW.Builder builder = mqttSessionBeginExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) - .typeId(mqttTypeId) - .session(sessionBuilder -> - { - sessionBuilder.clientId(clientId); - sessionBuilder.expiry(sessionExpiryInterval); - if (willFlagSet) - { - final int willFlags = decodeWillFlags(flags); - final int willQos = decodeWillQos(flags); - final MqttMessageFW.Builder willMessageBuilder = - mqttMessageFW.wrap(willMessageBuffer, 0, willMessageBuffer.capacity()) - .topic(payload.willTopic) - .delay(payload.willDelay) - .qos(willQos) - .flags(willFlags) - .expiryInterval(payload.expiryInterval) - .contentType(payload.contentType) - .format(f -> f.set(payload.payloadFormat)) - .responseTopic(payload.responseTopic) - .correlation(c -> c.bytes(payload.correlationData)); - - final Array32FW userProperties = willUserPropertiesRW.build(); - userProperties.forEach( - c -> willMessageBuilder.propertiesItem(p -> p.key(c.key()).value(c.value()))); - willMessageBuilder.payload(p -> p.bytes(payload.willPayload.bytes())); - sessionBuilder.will(willMessageBuilder.build()); - } - }); - - if (sessionStream == null) - { - sessionStream = new MqttSessionStream(originId, resolvedId, 0); - } + final MqttBeginExFW.Builder builder = mqttSessionBeginExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(s -> s + .flags(flags) + .expiry(sessionExpiry) + .clientId(clientId) + ); - sessionStream.doSessionBegin(traceId, authorization, affinity, builder.build()); + if (sessionStream == null) + { + sessionStream = new MqttSessionStream(originId, resolvedId, 0); } + + sessionStream.doSessionBegin(traceId, affinity, builder.build()); } private MqttPublishStream resolvePublishStream( @@ -1759,7 +1850,7 @@ private MqttPublishStream resolvePublishStream( final MqttBindingConfig binding = bindings.get(routedId); final MqttRouteConfig resolved = binding != null ? - binding.resolve(authorization, topic, MqttCapabilities.PUBLISH_ONLY) : null; + binding.resolvePublish(sessionId, topic) : null; if (resolved != null) { @@ -1767,7 +1858,7 @@ private MqttPublishStream resolvePublishStream( final int topicKey = topicKey(topic); stream = publishStreams.computeIfAbsent(topicKey, s -> new MqttPublishStream(routedId, resolvedId, topic)); - stream.doPublishBegin(traceId, authorization, affinity); + stream.doPublishBegin(traceId, affinity); } else { @@ -1784,32 +1875,49 @@ private void onDecodePublish( int reserved, OctetsFW payload) { - final int topicKey = topicKey(mqttPublishHeaderRO.topic); - MqttPublishStream stream = publishStreams.get(topicKey); + int reasonCode = SUCCESS; + if (mqttPublishHeaderRO.qos > maximumQos) + { + reasonCode = QOS_NOT_SUPPORTED; + } + else if (mqttPublishHeaderRO.retained && !retainAvailable(capabilities)) + { + reasonCode = RETAIN_NOT_SUPPORTED; + } - final MqttDataExFW.Builder builder = mqttPublishDataExRW.wrap(dataExtBuffer, 0, dataExtBuffer.capacity()) - .typeId(mqttTypeId) - .publish(publishBuilder -> - { - publishBuilder.topic(mqttPublishHeaderRO.topic); - publishBuilder.qos(mqttPublishHeaderRO.qos); - publishBuilder.flags(mqttPublishHeaderRO.flags); - publishBuilder.expiryInterval(mqttPublishHeaderRO.expiryInterval); - publishBuilder.contentType(mqttPublishHeaderRO.contentType); - publishBuilder.format(f -> f.set(mqttPublishHeaderRO.payloadFormat)); - publishBuilder.responseTopic(mqttPublishHeaderRO.responseTopic); - publishBuilder.correlation(c -> c.bytes(mqttPublishHeaderRO.correlationData)); - final Array32FW userProperties = userPropertiesRW.build(); - userProperties.forEach(c -> publishBuilder.propertiesItem(p -> p.key(c.key()).value(c.value()))); - }); + if (reasonCode != SUCCESS) + { + onDecodeError(traceId, authorization, reasonCode); + decoder = decodeIgnoreAll; + } + else + { + final int topicKey = topicKey(mqttPublishHeaderRO.topic); + MqttPublishStream stream = publishStreams.get(topicKey); + + final MqttDataExFW.Builder builder = mqttPublishDataExRW.wrap(dataExtBuffer, 0, dataExtBuffer.capacity()) + .typeId(mqttTypeId) + .publish(p -> + { + p.qos(mqttPublishHeaderRO.qos) + .flags(mqttPublishHeaderRO.flags) + .expiryInterval(mqttPublishHeaderRO.expiryInterval) + .contentType(mqttPublishHeaderRO.contentType) + .format(f -> f.set(mqttPublishHeaderRO.payloadFormat)) + .responseTopic(mqttPublishHeaderRO.responseTopic) + .correlation(c -> c.bytes(mqttPublishHeaderRO.correlationData)); + final Array32FW userProperties = userPropertiesRW.build(); + userProperties.forEach(c -> p.propertiesItem(pi -> pi.key(c.key()).value(c.value()))); + }); - final MqttDataExFW dataEx = builder.build(); - if (stream != null) - { - stream.doPublishData(traceId, authorization, reserved, payload, dataEx); + final MqttDataExFW dataEx = builder.build(); + if (stream != null) + { + stream.doPublishData(traceId, reserved, payload, dataEx); + } + doSignalKeepAliveTimeout(); } - doSignalKeepAliveTimeout(); } private void onDecodeSubscribe( @@ -1826,7 +1934,6 @@ private void onDecodeSubscribe( int subscriptionId = 0; boolean containsSubscriptionId = false; - int unrouteableMask = 0; MqttPropertiesFW properties = subscribe.properties(); final OctetsFW propertiesValue = properties.value(); @@ -1835,9 +1942,10 @@ private void onDecodeSubscribe( final int propertiesLimit = propertiesValue.limit(); MqttPropertyFW mqttProperty; - for (int progress = propertiesOffset; progress < propertiesLimit; progress = mqttProperty.limit()) + for (int propertiesProgress = propertiesOffset; + propertiesProgress < propertiesLimit; propertiesProgress = mqttProperty.limit()) { - mqttProperty = mqttPropertyRO.tryWrap(propertiesBuffer, progress, propertiesLimit); + mqttProperty = mqttPropertyRO.tryWrap(propertiesBuffer, propertiesProgress, propertiesLimit); switch (mqttProperty.kind()) { case KIND_SUBSCRIPTION_ID: @@ -1854,102 +1962,113 @@ private void onDecodeSubscribe( } else { - subscribePacketIds.put(subscriptionId, packetId); - final List newSubscriptions = new ArrayList<>(); - for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + decode: { - final MqttSubscribePayloadFW mqttSubscribePayload = - mqttSubscribePayloadRO.tryWrap(decodeBuffer, decodeProgress, decodeLimit); - if (mqttSubscribePayload == null) + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) { - break; - } - decodeProgress = mqttSubscribePayload.limit(); + final MqttSubscribePayloadFW mqttSubscribePayload = + mqttSubscribePayloadRO.tryWrap(decodeBuffer, decodeProgress, decodeLimit); + if (mqttSubscribePayload == null) + { + break; + } + decodeProgress = mqttSubscribePayload.limit(); - final String filter = mqttSubscribePayload.filter().asString(); - if (filter == null) - { - onDecodeError(traceId, authorization, PROTOCOL_ERROR); - decoder = decodeIgnoreAll; - break; - } + final String filter = mqttSubscribePayload.filter().asString(); + if (filter == null) + { + onDecodeError(traceId, authorization, PROTOCOL_ERROR); + decoder = decodeIgnoreAll; + break; + } - final boolean validTopicFilter = validator.isTopicFilterValid(filter); - if (!validTopicFilter) - { - onDecodeError(traceId, authorization, PROTOCOL_ERROR); - decoder = decodeIgnoreAll; - break; - } - if (wildcardSubscriptions == 0 && (filter.contains("+") || filter.contains("#"))) - { - onDecodeError(traceId, authorization, WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED); - decoder = decodeIgnoreAll; - break; - } + final boolean validTopicFilter = validator.isTopicFilterValid(filter); + if (!validTopicFilter) + { + onDecodeError(traceId, authorization, PROTOCOL_ERROR); + decoder = decodeIgnoreAll; + break; + } + if (!wildcardAvailable(capabilities) && (filter.contains("+") || filter.contains("#"))) + { + onDecodeError(traceId, authorization, WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED); + decoder = decodeIgnoreAll; + break; + } - if (sharedSubscriptions == 0 && filter.contains(SHARED_SUBSCRIPTION_LITERAL)) - { - onDecodeError(traceId, authorization, SHARED_SUBSCRIPTION_NOT_SUPPORTED); - decoder = decodeIgnoreAll; - break; - } - - if (subscriptionIdentifiers == 0 && containsSubscriptionId) - { - onDecodeError(traceId, authorization, SUBSCRIPTION_IDS_NOT_SUPPORTED); - decoder = decodeIgnoreAll; - break; - } - - final int options = mqttSubscribePayload.options(); - final int flags = calculateSubscribeFlags(traceId, authorization, options); + if (!sharedSubscriptionAvailable(capabilities) && filter.contains(SHARED_SUBSCRIPTION_LITERAL)) + { + onDecodeError(traceId, authorization, SHARED_SUBSCRIPTION_NOT_SUPPORTED); + decoder = decodeIgnoreAll; + break; + } - if (!noLocal && isSetNoLocal(flags)) - { - onDecodeError(traceId, authorization, PROTOCOL_ERROR); - decoder = decodeIgnoreAll; - break; - } + if (!subscriptionIdsAvailable(capabilities) && containsSubscriptionId) + { + onDecodeError(traceId, authorization, SUBSCRIPTION_IDS_NOT_SUPPORTED); + decoder = decodeIgnoreAll; + break; + } - Subscription subscription = new Subscription(); - subscription.id = subscriptionId; - subscription.filter = filter; - subscription.flags = flags; - newSubscriptions.add(subscription); - } + final int options = mqttSubscribePayload.options(); + final int flags = calculateSubscribeFlags(traceId, authorization, options); - if (session) - { - final MqttSessionStateFW.Builder sessionStateBuilder = - mqttSessionStateFW.wrap(sessionStateBuffer, 0, sessionStateBuffer.capacity()) - .clientId(clientId); + if (!noLocal && isSetNoLocal(flags)) + { + onDecodeError(traceId, authorization, PROTOCOL_ERROR); + decoder = decodeIgnoreAll; + break; + } - newSubscriptions.forEach(subscription -> + if (!containsSubscriptionId) { - sessionStateBuilder.subscriptionsItem(subscriptionBuilder -> - { - subscriptionBuilder.subscriptionId(subscription.id); - subscriptionBuilder.flags(subscription.flags); - subscriptionBuilder.pattern(subscription.filter); - }); - sessionStream.unAckedSubscriptions.add(subscription); + subscriptionId = supplySubscriptionId.getAsInt(); } + + Subscription subscription = new Subscription(); + subscription.id = subscriptionId; + subscription.filter = filter; + subscription.flags = flags; + subscribePacketIds.put(subscriptionId, packetId); + + newSubscriptions.add(subscription); + } + + final MqttDataExFW.Builder sessionDataExBuilder = + mqttSessionDataExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder.kind(k -> k.set(MqttSessionDataKind.STATE))); + + final MqttSessionStateFW.Builder state = + mqttSessionStateFW.wrap(sessionStateBuffer, 0, sessionStateBuffer.capacity()); + + sessionStream.unAckedSubscriptions.addAll(newSubscriptions); + sessionStream.subscriptions.forEach(sub -> + state.subscriptionsItem(subscriptionBuilder -> + subscriptionBuilder + .subscriptionId(sub.id) + .flags(sub.flags) + .pattern(sub.filter)) ); - final MqttSessionStateFW sessionState = sessionStateBuilder.build(); - final int payloadSize = sessionState.sizeof(); + newSubscriptions.forEach(sub -> + state.subscriptionsItem(subscriptionBuilder -> + subscriptionBuilder + .subscriptionId(sub.id) + .flags(sub.flags) + .pattern(sub.filter)) + ); - //TODO: is this correct? What is this? - int reserved = payloadSize; + final MqttSessionStateFW sessionState = state.build(); + final int payloadSize = sessionState.sizeof(); - sessionStream.doSessionData(traceId, authorization, reserved, sessionState); - } - else - { - openSubscribeStreams(packetId, traceId, authorization, newSubscriptions, false); + if (!sessionStream.hasSessionWindow(payloadSize)) + { + break decode; + } + sessionStream.doSessionData(traceId, payloadSize, sessionDataExBuilder.build(), sessionState); } } doSignalKeepAliveTimeout(); @@ -1960,15 +2079,26 @@ private void openSubscribeStreams( long traceId, long authorization, List subscriptions, - boolean adminSubscribe) + boolean implicitSubscribe) { final Long2ObjectHashMap> subscriptionsByRouteId = new Long2ObjectHashMap<>(); + if (!implicitSubscribe) + { + final byte[] subscriptionPayload = new byte[subscriptions.size()]; + for (int i = 0; i < subscriptionPayload.length; i++) + { + subscriptionPayload[i] = (byte) subscriptions.get(i).reasonCode; + } + + doEncodeSuback(traceId, sessionId, packetId, subscriptionPayload); + } + for (Subscription subscription : subscriptions) { final MqttBindingConfig binding = bindings.get(routedId); final MqttRouteConfig resolved = - binding != null ? binding.resolve(authorization, subscription.filter, MqttCapabilities.SUBSCRIBE_ONLY) : null; + binding != null ? binding.resolveSubscribe(sessionId, subscription.filter) : null; if (resolved != null) { @@ -1979,13 +2109,12 @@ private void openSubscribeStreams( subscriptionsByRouteId.forEach((key, value) -> { - int subscribeKey = subscribeKey(clientId.asString(), key); - MqttSubscribeStream stream = subscribeStreams.computeIfAbsent(subscribeKey, s -> - new MqttSubscribeStream(routedId, key, adminSubscribe)); + MqttSubscribeStream stream = subscribeStreams.computeIfAbsent(key, s -> + new MqttSubscribeStream(routedId, key, implicitSubscribe)); stream.packetId = packetId; - stream.doSubscribeBeginOrFlush(traceId, authorization, affinity, subscribeKey, value); + value.removeIf(s -> s.reasonCode > GRANTED_QOS_2); + stream.doSubscribeBeginOrFlush(traceId, affinity, value); }); - } private void onDecodeUnsubscribe( @@ -1999,12 +2128,6 @@ private void onDecodeUnsubscribe( final int decodeLimit = decodePayload.limit(); final int offset = decodePayload.offset(); - final MutableDirectBuffer encodeBuffer = payloadBuffer; - final int encodeOffset = 0; - final int encodeLimit = payloadBuffer.capacity(); - - int encodeProgress = encodeOffset; - int decodeReasonCode = SUCCESS; final List topicFilters = new ArrayList<>(); @@ -2036,58 +2159,59 @@ private void onDecodeUnsubscribe( } else { - if (session) - { - List unAckedSubscriptions = sessionStream.unAckedSubscriptions.stream() - .filter(s -> topicFilters.contains(s.filter) && subscribePacketIds.containsKey(s.id)) - .collect(Collectors.toList()); + List unAckedSubscriptions = sessionStream.unAckedSubscriptions.stream() + .filter(s -> topicFilters.contains(s.filter) && subscribePacketIds.containsKey(s.id)) + .collect(Collectors.toList()); - if (!unAckedSubscriptions.isEmpty()) - { - sessionStream.deferredUnsubscribes.put(packetId, topicFilters); - return; - } + if (!unAckedSubscriptions.isEmpty()) + { + sessionStream.deferredUnsubscribes.put(packetId, topicFilters); + return; + } + boolean matchingSubscription = topicFilters.stream().anyMatch(tf -> + sessionStream.subscriptions.stream().anyMatch(s -> s.filter.equals(tf))); + if (matchingSubscription) + { topicFilters.forEach(filter -> unsubscribePacketIds.put(filter, packetId)); - sendNewSessionStateForUnsubscribe(traceId, authorization, topicFilters); + doSendSessionState(traceId, topicFilters); } else { - sendUnsuback(packetId, traceId, authorization, topicFilters, false); + sendUnsuback(packetId, traceId, authorization, topicFilters, null, false); } doSignalKeepAliveTimeout(); } } - private void sendNewSessionStateForUnsubscribe( + private void doSendSessionState( long traceId, - long authorization, List topicFilters) { - List currentState = sessionStream.getSubscriptions(); + final MqttDataExFW.Builder sessionDataExBuilder = + mqttSessionDataExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder.kind(k -> k.set(MqttSessionDataKind.STATE))); + + List currentState = sessionStream.subscriptions(); List newState = currentState.stream() .filter(subscription -> !topicFilters.contains(subscription.filter)) .collect(Collectors.toList()); final MqttSessionStateFW.Builder sessionStateBuilder = - mqttSessionStateFW.wrap(sessionStateBuffer, 0, sessionStateBuffer.capacity()) - .clientId(clientId); + mqttSessionStateFW.wrap(sessionStateBuffer, 0, sessionStateBuffer.capacity()); newState.forEach(subscription -> - sessionStateBuilder.subscriptionsItem(subscriptionBuilder -> - { - subscriptionBuilder.pattern(subscription.filter); - subscriptionBuilder.subscriptionId(subscription.id); - subscriptionBuilder.flags(subscription.flags); - }) + sessionStateBuilder.subscriptionsItem(s -> + s.subscriptionId(subscription.id) + .qos(subscription.qos) + .flags(subscription.flags) + .pattern(subscription.filter)) ); final MqttSessionStateFW sessionState = sessionStateBuilder.build(); final int payloadSize = sessionState.sizeof(); - //TODO: is this correct? What is this? - int reserved = payloadSize; - - sessionStream.doSessionData(traceId, authorization, reserved, sessionState); + sessionStream.doSessionData(traceId, payloadSize, sessionDataExBuilder.build(), sessionState); } private void sendUnsuback( @@ -2095,6 +2219,7 @@ private void sendUnsuback( long traceId, long authorization, List topicFilters, + List newState, boolean adminUnsubscribe) { final MutableDirectBuffer encodeBuffer = payloadBuffer; @@ -2103,21 +2228,20 @@ private void sendUnsuback( int encodeProgress = encodeOffset; - final Map> filtersByStream = new HashMap<>(); + final Map> filtersByStream = new HashMap<>(); for (String topicFilter : topicFilters) { final MqttBindingConfig binding = bindings.get(routedId); final MqttRouteConfig resolved = - binding != null ? binding.resolve(authorization, topicFilter, MqttCapabilities.SUBSCRIBE_ONLY) : null; - final int subscribeKey = subscribeKey(clientId.asString(), resolved.id); - final MqttSubscribeStream stream = subscribeStreams.get(subscribeKey); + binding != null ? binding.resolveSubscribe(sessionId, topicFilter) : null; + final MqttSubscribeStream stream = subscribeStreams.get(resolved.id); - filtersByStream.computeIfAbsent(stream, s -> new ArrayList<>()).add(topicFilter); - Optional subscription = stream.getSubscriptionByFilter(topicFilter); + Optional subscription = stream.getSubscriptionByFilter(topicFilter, newState); - int encodeReasonCode = subscription.isPresent() ? SUCCESS : NO_SUBSCRIPTION_EXISTED; + subscription.ifPresent(value -> filtersByStream.computeIfAbsent(stream, s -> new ArrayList<>()).add(value)); + int encodeReasonCode = subscription.isPresent() ? subscription.get().reasonCode : NO_SUBSCRIPTION_EXISTED; final MqttUnsubackPayloadFW mqttUnsubackPayload = mqttUnsubackPayloadRW.wrap(encodeBuffer, encodeProgress, encodeLimit) .reasonCode(encodeReasonCode) @@ -2126,7 +2250,7 @@ private void sendUnsuback( } filtersByStream.forEach( - (stream, filters) -> stream.doSubscribeFlushOrEnd(traceId, authorization, filters)); + (stream, subscriptions) -> stream.doSubscribeFlushOrEnd(traceId, subscriptions)); if (!adminUnsubscribe) { final OctetsFW encodePayload = octetsRO.wrap(encodeBuffer, encodeOffset, encodeProgress); @@ -2148,22 +2272,71 @@ private void onDecodeDisconnect( long authorization, MqttDisconnectFW disconnect) { - state = MqttState.closingInitial(state); - publishStreams.values().forEach(s -> s.doPublishNetEnd(traceId, authorization, EMPTY_OCTETS)); - subscribeStreams.values().forEach(s -> s.doSubscribeNetEnd(traceId, authorization)); - if (session) + byte reasonCode = disconnect != null ? decodeDisconnectProperties(disconnect.properties()) : SUCCESS; + + if (reasonCode != SUCCESS) { - final MqttEndExFW.Builder builder = mqttEndExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) - .typeId(mqttTypeId) - .reasonCode(r -> r.set( - disconnect.reasonCode() == DISCONNECT_WITH_WILL_MESSAGE ? - MqttEndReasonCode.DISCONNECT_WITH_WILL : - MqttEndReasonCode.DISCONNECT)); - sessionStream.doSessionAppEnd(traceId, authorization, builder.build()); + onDecodeError(traceId, authorization, reasonCode); + decoder = decodeIgnoreAll; + } + else + { + if (disconnect != null && disconnect.reasonCode() == DISCONNECT_WITH_WILL_MESSAGE) + { + sessionStream.doSessionAbort(traceId); + } + else + { + sessionStream.doSessionAppEnd(traceId, EMPTY_OCTETS); + } } + + state = MqttState.closingInitial(state); + closeStreams(traceId, authorization); doNetworkEnd(traceId, authorization); } + private byte decodeDisconnectProperties( + MqttPropertiesFW properties) + { + byte reasonCode = SUCCESS; + + final OctetsFW propertiesValue = properties.value(); + final DirectBuffer decodeBuffer = propertiesValue.buffer(); + final int decodeOffset = propertiesValue.offset(); + final int decodeLimit = propertiesValue.limit(); + + decode: + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + { + final MqttPropertyFW mqttProperty = mqttPropertyRO.wrap(decodeBuffer, decodeProgress, decodeLimit); + switch (mqttProperty.kind()) + { + case KIND_SESSION_EXPIRY: + if (isSetSessionExpiryInterval(decodablePropertyMask)) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + this.decodablePropertyMask |= CONNECT_SESSION_EXPIRY_INTERVAL_MASK; + final int sessionExpiryInterval = (int) mqttProperty.sessionExpiry(); + if (sessionExpiryInterval > 0 && this.sessionExpiry == 0) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } + break; + default: + reasonCode = MALFORMED_PACKET; + break decode; + } + + decodeProgress = mqttProperty.limit(); + } + + return reasonCode; + } + private void onDecodeError( long traceId, long authorization, @@ -2172,19 +2345,19 @@ private void onDecodeError( switch (reasonCode) { case SESSION_TAKEN_OVER: - cleanupStreamsUsingEnd(traceId, authorization); + closeStreams(traceId, authorization); break; default: - cleanupStreamsUsingAbort(traceId, authorization); + cleanupStreamsUsingAbort(traceId); break; } if (connected) { - doEncodeDisconnect(traceId, authorization, reasonCode); + doEncodeDisconnect(traceId, authorization, reasonCode, null); } else { - doEncodeConnack(traceId, authorization, reasonCode, false, false); + doEncodeConnack(traceId, authorization, reasonCode, false, false, null); } doNetworkEnd(traceId, authorization); @@ -2322,6 +2495,7 @@ private void doEncodePublish( final int expiryInterval = subscribeDataEx.subscribe().expiryInterval(); final String16FW contentType = subscribeDataEx.subscribe().contentType(); final String16FW responseTopic = subscribeDataEx.subscribe().responseTopic(); + final MqttPayloadFormatFW format = subscribeDataEx.subscribe().format(); final MqttBinaryFW correlation = subscribeDataEx.subscribe().correlation(); final Array32FW subscriptionIds = subscribeDataEx.subscribe().subscriptionIds(); final Array32FW properties = @@ -2335,16 +2509,17 @@ private void doEncodePublish( MutableBoolean retainAsPublished = new MutableBoolean(false); - subscriptionIds.forEach(subscriptionId -> + subscriptionIds.forEach(s -> { - if (subscriptionId.value() > 0) + final int subscriptionId = s.value(); + if (subscriptionId > 0 && !generatedSubscriptionId(subscriptionId)) { Optional result = subscriptions.stream() - .filter(subscription -> subscription.id == subscriptionId.value()) + .filter(subscription -> subscription.id == subscriptionId) .findFirst(); retainAsPublished.set(retainAsPublished.value | result.isPresent() && result.get().retainAsPublished()); mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) - .subscriptionId(v -> v.set(subscriptionId.value())); + .subscriptionId(v -> v.set(subscriptionId)); propertiesSize.set(mqttPropertyRW.limit()); } }); @@ -2372,11 +2547,13 @@ private void doEncodePublish( propertiesSize.set(mqttPropertyRW.limit()); } - // TODO: optional format - mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) - .payloadFormat((byte) subscribeDataEx.subscribe().format().get().ordinal()) - .build(); - propertiesSize.set(mqttPropertyRW.limit()); + if (!format.get().equals(MqttPayloadFormat.NONE)) + { + mqttPropertyRW.wrap(propertyBuffer, propertiesSize.get(), propertyBuffer.capacity()) + .payloadFormat((byte) subscribeDataEx.subscribe().format().get().ordinal()) + .build(); + propertiesSize.set(mqttPropertyRW.limit()); + } if (responseTopic.value() != null) { @@ -2421,6 +2598,12 @@ private void doEncodePublish( } } + private boolean generatedSubscriptionId( + int subscriptionId) + { + return (subscriptionId & GENERATED_SUBSCRIPTION_ID_MASK) == GENERATED_SUBSCRIPTION_ID_MASK; + } + private int calculatePublishNetworkFlags(int applicationTypeAndFlags, int qos) { int flags = 0; @@ -2446,17 +2629,24 @@ private void doEncodeConnack( long authorization, int reasonCode, boolean assignedClientId, - boolean sessionPresent) + boolean sessionPresent, + String16FW serverReference) { int propertiesSize = 0; MqttPropertyFW mqttProperty; if (reasonCode == SUCCESS) { - if (sessionExpiryInterval > sessionExpiryIntervalLimit) + //TODO: remove this once we support large messages + mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) + .maximumPacketSize(maximumPacketSize) + .build(); + propertiesSize = mqttProperty.limit(); + + if (connectSessionExpiry != sessionExpiry) { mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) - .sessionExpiry(sessionExpiryIntervalLimit) + .sessionExpiry(sessionExpiry) .build(); propertiesSize = mqttProperty.limit(); } @@ -2464,15 +2654,15 @@ private void doEncodeConnack( if (0 <= maximumQos && maximumQos < 2) { mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) - .maximumQoS(maximumQos) + .maximumQoS((byte) maximumQos) .build(); propertiesSize = mqttProperty.limit(); } - if (retainedMessages == 0) + if (!retainAvailable(capabilities)) { mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) - .retainAvailable(retainedMessages) + .retainAvailable((byte) 0) .build(); propertiesSize = mqttProperty.limit(); } @@ -2485,26 +2675,26 @@ private void doEncodeConnack( propertiesSize = mqttProperty.limit(); } - if (wildcardSubscriptions == 0) + if (!subscriptionIdsAvailable(capabilities)) { mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) - .wildcardSubscriptionAvailable(wildcardSubscriptions) + .subscriptionIdsAvailable((byte) 0) .build(); propertiesSize = mqttProperty.limit(); } - if (subscriptionIdentifiers == 0) + if (!sharedSubscriptionAvailable(capabilities)) { mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) - .subscriptionIdsAvailable(subscriptionIdentifiers) + .sharedSubscriptionAvailable((byte) 0) .build(); propertiesSize = mqttProperty.limit(); } - if (sharedSubscriptions == 0) + if (!wildcardAvailable(capabilities)) { mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) - .sharedSubscriptionAvailable(sharedSubscriptions) + .wildcardSubscriptionAvailable((byte) 0) .build(); propertiesSize = mqttProperty.limit(); } @@ -2526,6 +2716,14 @@ private void doEncodeConnack( } } + if (serverReference != null) + { + mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) + .serverReference(serverReference) + .build(); + propertiesSize = mqttProperty.limit(); + } + int flags = sessionPresent ? CONNACK_SESSION_PRESENT : 0x00; final int propertiesSize0 = propertiesSize; @@ -2597,14 +2795,28 @@ private void doEncodePingResp( private void doEncodeDisconnect( long traceId, long authorization, - int reasonCode) + int reasonCode, + String16FW serverReference) { + int propertiesSize = 0; + + MqttPropertyFW mqttProperty; + if (serverReference != null) + { + mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) + .serverReference(serverReference) + .build(); + propertiesSize = mqttProperty.limit(); + } + + final int propertySize0 = propertiesSize; final MqttDisconnectFW disconnect = mqttDisconnectRW.wrap(writeBuffer, FIELD_OFFSET_PAYLOAD, writeBuffer.capacity()) .typeAndFlags(0xe0) - .remainingLength(2) + .remainingLength(2 + propertySize0) .reasonCode(reasonCode & 0xff) - .properties(p -> p.length(0).value(EMPTY_OCTETS)) + .properties(p -> p.length(propertySize0) + .value(propertyBuffer, 0, propertySize0)) .build(); doNetworkData(traceId, authorization, 0L, disconnect); @@ -2726,7 +2938,7 @@ private void decodeNetwork( if (MqttState.initialClosing(state)) { state = MqttState.closeInitial(state); - cleanupStreamsUsingAbort(traceId, authorization); + cleanupStreamsUsingAbort(traceId); doNetworkEnd(traceId, authorization); } } @@ -2741,33 +2953,32 @@ private void cleanupNetwork( long traceId, long authorization) { - cleanupStreamsUsingAbort(traceId, authorization); + cleanupStreamsUsingAbort(traceId); doNetworkReset(traceId, authorization); doNetworkAbort(traceId, authorization); } private void cleanupStreamsUsingAbort( - long traceId, - long authorization) + long traceId) { - publishStreams.values().forEach(s -> s.cleanupAbort(traceId, authorization)); - subscribeStreams.values().forEach(s -> s.cleanupAbort(traceId, authorization)); + publishStreams.values().forEach(s -> s.cleanupAbort(traceId)); + subscribeStreams.values().forEach(s -> s.cleanupAbort(traceId)); if (sessionStream != null) { - sessionStream.cleanupAbort(traceId, authorization); + sessionStream.cleanupAbort(traceId); } } - private void cleanupStreamsUsingEnd( + private void closeStreams( long traceId, long authorization) { - publishStreams.values().forEach(s -> s.cleanupEnd(traceId, authorization)); - subscribeStreams.values().forEach(s -> s.cleanupEnd(traceId, authorization)); + publishStreams.values().forEach(s -> s.doPublishAppEnd(traceId)); + subscribeStreams.values().forEach(s -> s.doSubscribeAppEnd(traceId)); if (sessionStream != null) { - sessionStream.cleanupEnd(traceId, authorization); + sessionStream.cleanupEnd(traceId); } } @@ -2864,6 +3075,7 @@ private final class Subscription private String filter; private int qos; private int flags; + private int reasonCode; private boolean retainAsPublished() { @@ -2883,13 +3095,13 @@ public boolean equals(Object obj) } Subscription other = (Subscription) obj; return this.id == other.id && Objects.equals(this.filter, other.filter) && - this.qos == other.qos && this.flags == other.flags; + this.qos == other.qos && this.flags == other.flags && this.reasonCode == other.reasonCode; } @Override public int hashCode() { - return Objects.hash(this.id, this.filter, this.qos, this.flags); + return Objects.hash(this.id, this.filter, this.qos, this.flags, this.reasonCode); } } @@ -2971,10 +3183,6 @@ private void onSession( final ResetFW reset = resetRO.wrap(buffer, index, index + length); onSessionReset(reset); break; - case SignalFW.TYPE_ID: - final SignalFW signal = signalRO.wrap(buffer, index, index + length); - onSessionSignal(signal); - break; } } @@ -2988,6 +3196,7 @@ private void onSessionWindow( final long authorization = window.authorization(); final long budgetId = window.budgetId(); final int padding = window.padding(); + final boolean wasOpen = MqttState.initialOpened(state); if (!MqttState.initialOpened(state)) { @@ -3008,6 +3217,11 @@ private void onSessionWindow( assert initialAck <= initialSeq; + if (!wasOpen) + { + decodeNetwork(traceId); + } + if (budgetId != 0L && debitorIndex == NO_DEBITOR_INDEX) { debitor = supplyDebitor.apply(budgetId); @@ -3016,7 +3230,7 @@ private void onSessionWindow( if (MqttState.initialClosing(state) && !MqttState.initialClosed(state)) { - doSessionAppEnd(traceId, authorization, EMPTY_OCTETS); + doSessionAppEnd(traceId, EMPTY_OCTETS); } } @@ -3026,28 +3240,36 @@ private void onSessionReset( final long traceId = reset.traceId(); final long authorization = reset.authorization(); - if (!MqttState.initialOpened(state)) - { - doCancelConnectTimeout(); - doEncodeConnack(traceId, authorization, SUCCESS, assignedClientId, false); - } + final OctetsFW extension = reset.extension(); + final MqttResetExFW mqttResetEx = extension.get(mqttResetExRO::tryWrap); - setInitialClosed(); - decodeNetwork(traceId); - cleanupAbort(traceId, authorization); - } - - private void onSessionSignal( - SignalFW signal) - { - final int signalId = signal.signalId(); - switch (signalId) + if (mqttResetEx != null) { - default: - break; + String16FW serverRef = mqttResetEx.serverRef(); + byte reasonCode = (byte) mqttResetEx.reasonCode(); + boolean serverRefExists = serverRef != null && serverRef.asString() != null; + + if (reasonCode == SUCCESS) + { + reasonCode = serverRefExists ? SERVER_MOVED : SESSION_TAKEN_OVER; + } + + if (!connected) + { + doCancelConnectTimeout(); + doEncodeConnack(traceId, authorization, reasonCode, assignedClientId, + false, serverRefExists ? serverRef : null); + } + else + { + doEncodeDisconnect(traceId, authorization, reasonCode, serverRefExists ? serverRef : null); + } } + setInitialClosed(); + decodeNetwork(traceId); + cleanupAbort(traceId); } private void onSessionBegin( @@ -3056,9 +3278,22 @@ private void onSessionBegin( state = MqttState.openReply(state); final long traceId = begin.traceId(); - final long authorization = begin.authorization(); - doSessionWindow(traceId, authorization, encodeSlotOffset, encodeBudgetMax); + final OctetsFW extension = begin.extension(); + if (extension.sizeof() > 0) + { + final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); + + assert mqttBeginEx.kind() == MqttBeginExFW.KIND_SESSION; + final MqttSessionBeginExFW mqttSessionBeginEx = mqttBeginEx.session(); + + sessionExpiry = mqttSessionBeginEx.expiry(); + capabilities = mqttSessionBeginEx.capabilities(); + maximumQos = mqttSessionBeginEx.qosMax(); + maximumPacketSize = (int) mqttSessionBeginEx.packetSizeMax(); + } + + doSessionWindow(traceId, encodeSlotOffset, encodeBudgetMax); } private void onSessionData( @@ -3084,7 +3319,7 @@ private void onSessionData( if (replySeq > replyAck + replyMax) { - doSessionReset(traceId, authorization); + doSessionReset(traceId); doNetworkAbort(traceId, authorization); } else @@ -3101,9 +3336,9 @@ private void onSessionData( boolean sessionPresent = false; if (sessionState != null) { - if (cleanStart) + if (isCleanStart(connectFlags)) { - doSessionData(traceId, authorization, 0, emptyRO); + doSessionData(traceId, 0, emptyRO, emptyRO); } else { @@ -3116,11 +3351,12 @@ private void onSessionData( subscription.flags = filter.flags(); subscriptions.add(subscription); }); - openSubscribeStreams(packetId, traceId, authorization, subscriptions, true); + + openSubscribeStreams(0, traceId, authorization, subscriptions, true); sessionPresent = true; } } - doEncodeConnack(traceId, authorization, reasonCode, assignedClientId, sessionPresent); + doEncodeConnack(traceId, authorization, reasonCode, assignedClientId, sessionPresent, null); connected = true; } else @@ -3134,10 +3370,11 @@ private void onSessionData( subscription.id = (int) filter.subscriptionId(); subscription.filter = filter.pattern().asString(); subscription.flags = filter.flags(); + subscription.reasonCode = filter.reasonCode(); newState.add(subscription); }); - List currentSubscriptions = sessionStream.getSubscriptions(); - if (newState.size() > currentSubscriptions.size()) + List currentSubscriptions = sessionStream.subscriptions(); + if (newState.size() >= currentSubscriptions.size()) { List newSubscriptions = newState.stream() .filter(s -> !currentSubscriptions.contains(s)) @@ -3156,25 +3393,25 @@ private void onSessionData( } else { - List removedFilters = currentSubscriptions.stream() + final List unsubscribedFilters = currentSubscriptions.stream() .filter(s -> !newState.contains(s)) .map(s -> s.filter) .collect(Collectors.toList()); - if (!removedFilters.isEmpty()) + if (!unsubscribedFilters.isEmpty()) { - Map> packetIdToFilters = removedFilters.stream() + Map> packetIdToFilters = unsubscribedFilters.stream() .filter(unsubscribePacketIds::containsKey) .collect(Collectors.groupingBy(unsubscribePacketIds::remove, Collectors.toList())); if (!packetIdToFilters.isEmpty()) { packetIdToFilters.forEach((unsubscribePacketId, filters) -> - sendUnsuback(unsubscribePacketId, traceId, authorization, filters, false)); + sendUnsuback(unsubscribePacketId, traceId, authorization, filters, newState, false)); } else { - sendUnsuback(packetId, traceId, authorization, removedFilters, true); + sendUnsuback(packetId, traceId, authorization, unsubscribedFilters, newState, true); } } } @@ -3182,7 +3419,7 @@ private void onSessionData( } } - doSessionWindow(traceId, authorization, encodeSlotOffset, encodeBudgetMax); + doSessionWindow(traceId, encodeSlotOffset, encodeBudgetMax); } } @@ -3204,14 +3441,12 @@ private void onSessionAbort( setReplyClosed(); final long traceId = abort.traceId(); - final long authorization = abort.authorization(); - cleanupAbort(traceId, authorization); + cleanupAbort(traceId); } private void doSessionBegin( long traceId, - long authorization, long affinity, Flyweight beginEx) { @@ -3220,32 +3455,39 @@ private void doSessionBegin( assert state == 0; state = MqttState.openingInitial(state); - application = newStream(this::onSession, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, beginEx); + traceId, sessionId, affinity, beginEx); - doSessionWindow(traceId, authorization, 0, 0); + doSessionWindow(traceId, 0, 0); } } + private boolean hasSessionWindow( + int length) + { + return initialMax - (initialSeq - initialAck) >= length + initialPad; + } + private void doSessionData( long traceId, - long authorization, int reserved, - Flyweight sessionState) + Flyweight dataEx, + Flyweight payload) { assert MqttState.initialOpening(state); - final DirectBuffer buffer = sessionState.buffer(); - final int offset = sessionState.offset(); - final int limit = sessionState.limit(); + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); final int length = limit - offset; assert reserved >= length + initialPad; + reserved += initialPad; + if (!MqttState.closed(state)) { doData(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, buffer, offset, length, EMPTY_OCTETS); + traceId, sessionId, budgetId, reserved, buffer, offset, length, dataEx); initialSeq += reserved; assert initialSeq <= initialAck + initialMax; @@ -3253,66 +3495,43 @@ private void doSessionData( } private void cleanupAbort( - long traceId, - long authorization) + long traceId) { - doSessionAbort(traceId, authorization); - doSessionReset(traceId, authorization); + doSessionAbort(traceId); + doSessionReset(traceId); } private void cleanupEnd( - long traceId, - long authorization) + long traceId) { - doSessionNetEnd(traceId, authorization, EMPTY_OCTETS); - doSessionAppEnd(traceId, authorization, EMPTY_OCTETS); - } - - private void doSessionNetEnd( - long traceId, - long authorization, - Flyweight extension) - { - if (MqttState.initialOpening(state) && !MqttState.initialClosed(state)) - { - setInitialClosed(); - - doEnd(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, extension); - } + doSessionAppEnd(traceId, EMPTY_OCTETS); } private void doSessionAbort( - long traceId, - long authorization) + long traceId) { if (!MqttState.initialClosed(state)) { setInitialClosed(); doAbort(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, EMPTY_OCTETS); + traceId, sessionId, EMPTY_OCTETS); } } private void doSessionAppEnd( long traceId, - long authorization, Flyweight extension) { if (MqttState.initialOpening(state) && !MqttState.initialClosed(state)) { - setReplyClosed(); - doEnd(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, extension); - sessionStream = null; + traceId, sessionId, extension); } } private void doSessionWindow( long traceId, - long authorization, int minReplyNoAck, int minReplyMax) { @@ -3328,21 +3547,20 @@ private void doSessionWindow( replyMax = minReplyMax; doWindow(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, encodeBudgetId, PUBLISH_FRAMING); + traceId, sessionId, encodeBudgetId, PUBLISH_FRAMING); } } } private void doSessionReset( - long traceId, - long authorization) + long traceId) { if (!MqttState.replyClosed(state)) { setReplyClosed(); doReset(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, EMPTY_OCTETS); + traceId, sessionId, EMPTY_OCTETS); } } @@ -3351,11 +3569,6 @@ private void setReplyClosed() assert !MqttState.replyClosed(state); state = MqttState.closeReply(state); - - if (MqttState.closed(state)) - { - sessionStream = null; - } } private void setInitialClosed() @@ -3369,18 +3582,13 @@ private void setInitialClosed() debitor.release(debitorIndex, initialId); debitorIndex = NO_DEBITOR_INDEX; } - - if (MqttState.closed(state)) - { - sessionStream = null; - } } public void setSubscriptions(List subscriptions) { this.subscriptions = subscriptions; } - public List getSubscriptions() + public List subscriptions() { return subscriptions; } @@ -3429,7 +3637,6 @@ private class MqttPublishStream private void doPublishBegin( long traceId, - long authorization, long affinity) { if (!MqttState.initialOpening(state)) @@ -3439,24 +3646,22 @@ private void doPublishBegin( final MqttBeginExFW beginEx = mqttPublishBeginExRW.wrap(extBuffer, 0, extBuffer.capacity()) .typeId(mqttTypeId) - .publish(publishBuilder -> - { - publishBuilder.clientId(clientId); - publishBuilder.topic(topic); - }) + .publish(p -> + p.clientId(clientId) + .topic(topic) + .flags(retainAvailable(capabilities) ? 1 : 0)) .build(); application = newStream(this::onPublish, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, beginEx); + traceId, sessionId, affinity, beginEx); doSignalPublishExpiration(); - doPublishWindow(traceId, authorization, 0, 0); + doPublishWindow(traceId, 0, 0); } } private void doPublishData( long traceId, - long authorization, int reserved, OctetsFW payload, Flyweight extension) @@ -3470,7 +3675,7 @@ private void doPublishData( assert reserved >= length + initialPad; doData(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, buffer, offset, length, extension); + traceId, sessionId, budgetId, reserved, buffer, offset, length, extension); initialSeq += reserved; assert initialSeq <= initialAck + initialMax; @@ -3479,30 +3684,14 @@ private void doPublishData( } private void doPublishAbort( - long traceId, - long authorization) + long traceId) { if (!MqttState.initialClosed(state)) { setPublishNetClosed(); doAbort(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, EMPTY_OCTETS); - } - } - - private void doPublishNetEnd( - long traceId, - long authorization, - Flyweight extension) - { - if (MqttState.initialOpening(state) && !MqttState.initialClosed(state)) - { - setPublishNetClosed(); - publishStreams.remove(topicKey); - - doEnd(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, extension); + traceId, sessionId, EMPTY_OCTETS); } } @@ -3551,10 +3740,8 @@ private void onPublishBegin( state = MqttState.openingReply(state); final long traceId = begin.traceId(); - final long authorization = begin.authorization(); - - doPublishWindow(traceId, authorization, encodeSlotOffset, encodeBudgetMax); + doPublishWindow(traceId, encodeSlotOffset, encodeBudgetMax); } private void onPublishData( @@ -3577,13 +3764,13 @@ private void onPublishData( if (replySeq > replyAck + replyMax) { - doPublishReset(traceId, authorization); + doPublishReset(traceId); doNetworkAbort(traceId, authorization); } else { droppedHandler.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); - doPublishWindow(traceId, authorization, encodeSlotOffset, encodeBudgetMax); + doPublishWindow(traceId, encodeSlotOffset, encodeBudgetMax); } } @@ -3599,9 +3786,8 @@ private void onPublishAbort( setPublishAppClosed(); final long traceId = abort.traceId(); - final long authorization = abort.authorization(); - cleanupAbort(traceId, authorization); + cleanupAbort(traceId); } private void onPublishWindow( @@ -3635,10 +3821,9 @@ private void onPublishWindow( debitorIndex = debitor.acquire(budgetId, initialId, MqttServer.this::decodeNetwork); } - if (MqttState.initialClosing(state) && - !MqttState.initialClosed(state)) + if (MqttState.initialClosing(state)) { - doPublishNetEnd(traceId, authorization, EMPTY_OCTETS); + doPublishAppEnd(traceId); } else if (decodePublisherKey == topicKey) { @@ -3661,7 +3846,7 @@ private void onPublishReset( } decodeNetwork(traceId); - cleanupAbort(traceId, authorization); + cleanupAbort(traceId); } private void onPublishSignal( @@ -3683,12 +3868,11 @@ private void onPublishExpiredSignal( SignalFW signal) { final long traceId = signal.traceId(); - final long authorization = signal.authorization(); final long now = System.currentTimeMillis(); if (now >= publishExpiresAt) { - doPublishNetEnd(traceId, authorization, EMPTY_OCTETS); + doPublishAppEnd(traceId); } else { @@ -3719,7 +3903,6 @@ private void doCancelPublishExpiration() private void doPublishWindow( long traceId, - long authorization, int minReplyNoAck, int minReplyMax) { @@ -3737,33 +3920,31 @@ private void doPublishWindow( state = MqttState.openReply(state); doWindow(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, encodeBudgetId, PUBLISH_FRAMING); + traceId, sessionId, encodeBudgetId, PUBLISH_FRAMING); } } } private void doPublishReset( - long traceId, - long authorization) + long traceId) { if (!MqttState.replyClosed(state)) { setPublishAppClosed(); doReset(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, EMPTY_OCTETS); + traceId, sessionId, EMPTY_OCTETS); } } private void doPublishAppEnd( - long traceId, - long authorization) + long traceId) { - if (!MqttState.replyClosed(state)) + if (!MqttState.initialClosed(state)) { - setPublishAppClosed(); - doEnd(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, EMPTY_OCTETS); + doCancelPublishExpiration(); + doEnd(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, sessionId, EMPTY_OCTETS); } } @@ -3799,20 +3980,10 @@ private void setPublishAppClosed() } private void cleanupAbort( - long traceId, - long authorization) - { - doPublishAbort(traceId, authorization); - doPublishReset(traceId, authorization); - doCancelPublishExpiration(); - } - - private void cleanupEnd( - long traceId, - long authorization) + long traceId) { - doPublishNetEnd(traceId, authorization, EMPTY_OCTETS); - doPublishAppEnd(traceId, authorization); + doPublishAbort(traceId); + doPublishReset(traceId); doCancelPublishExpiration(); } } @@ -3841,7 +4012,6 @@ private class MqttSubscribeStream private int state; private final List subscriptions; private boolean acknowledged; - private int clientKey; private int packetId; private final boolean adminSubscribe; @@ -3858,34 +4028,35 @@ private class MqttSubscribeStream this.adminSubscribe = adminSubscribe; } - private Optional getSubscriptionByFilter(String filter) + private Optional getSubscriptionByFilter( + String filter, + List newState) { - return subscriptions.stream().filter(s -> s.filter.equals(filter)).findFirst(); + return Optional.ofNullable(newState) + .flatMap(list -> list.stream().filter(s -> s.filter.equals(filter)).findFirst()) + .or(() -> subscriptions.stream().filter(s -> s.filter.equals(filter)).findFirst()); + } private void doSubscribeBeginOrFlush( long traceId, - long authorization, long affinity, - int clientKey, List subscriptions) { this.subscriptions.addAll(subscriptions); - this.clientKey = clientKey; if (!MqttState.initialOpening(state)) { - doSubscribeBegin(traceId, authorization, affinity); + doSubscribeBegin(traceId, affinity); } else { - doSubscribeFlush(traceId, authorization, 0, subscriptions); + doSubscribeFlush(traceId, 0); } } private void doSubscribeBegin( long traceId, - long authorization, long affinity) { assert state == 0; @@ -3908,19 +4079,17 @@ private void doSubscribeBegin( .build(); application = newStream(this::onSubscribe, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, beginEx); + traceId, sessionId, affinity, beginEx); - doSubscribeWindow(traceId, authorization, 0, 0); + doSubscribeWindow(traceId, 0, 0); } private void doSubscribeFlush( long traceId, - long authorization, - int reserved, - List newSubscriptions) + int reserved) { doFlush(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, 0L, reserved, + traceId, sessionId, 0L, reserved, ex -> ex.set((b, o, l) -> mqttFlushExRW.wrap(b, o, l) .typeId(mqttTypeId) .subscribe(subscribeBuilder -> @@ -3935,70 +4104,40 @@ private void doSubscribeFlush( .build() .sizeof())); - if (newSubscriptions != null && !newSubscriptions.isEmpty()) - { - // TODO: do we get back anything after we send a flush? - // Should we say it's a success right after we sent the flush? - final byte[] subscriptionPayload = new byte[newSubscriptions.size()]; - for (int i = 0; i < subscriptionPayload.length; i++) - { - subscriptionPayload[i] = SUCCESS; - } - - doEncodeSuback(traceId, authorization, packetId, subscriptionPayload); - } - initialSeq += reserved; assert initialSeq <= initialAck + initialMax; } private void doSubscribeFlushOrEnd( long traceId, - long authorization, - List unsubscribedPatterns) + List unsubscribed) { - this.subscriptions.removeIf(subscription -> unsubscribedPatterns.contains(subscription.filter)); + for (Subscription subscription : unsubscribed) + { + if (subscription.reasonCode == SUCCESS) + { + this.subscriptions.remove(subscription); + } + } if (!MqttState.initialOpened(state)) { state = MqttState.closingInitial(state); } else { - if (subscriptions.isEmpty()) - { - doSubscribeNetEnd(traceId, authorization); - } - else - { - doSubscribeFlush(traceId, authorization, 0, null); - } - } - } - - private void doSubscribeNetEnd( - long traceId, - long authorization) - { - if (MqttState.initialOpening(state) && !MqttState.initialClosed(state)) - { - setNetClosed(); - subscribeStreams.remove(clientKey); - - doEnd(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, EMPTY_OCTETS); + doSubscribeFlush(traceId, 0); } } private void doSubscribeAbort( - long traceId, - long authorization) + long traceId) { if (!MqttState.initialClosed(state)) { setNetClosed(); doAbort(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, EMPTY_OCTETS); + traceId, sessionId, EMPTY_OCTETS); } } @@ -4016,7 +4155,7 @@ private void setNetClosed() if (MqttState.closed(state)) { - subscribeStreams.remove(clientKey); + subscribeStreams.remove(routedId); } } @@ -4065,12 +4204,12 @@ private void onSubscribeBegin( if (!acknowledged) { - doSubscribeWindow(traceId, authorization, encodeSlotOffset, encodeBudgetMax); + doSubscribeWindow(traceId, encodeSlotOffset, encodeBudgetMax); acknowledged = true; } else { - doSubscribeWindow(traceId, authorization, 0, replyMax); + doSubscribeWindow(traceId, 0, replyMax); } } @@ -4098,7 +4237,7 @@ private void onSubscribeData( if (replySeq > replyAck + replyMax) { - doSubscribeReset(traceId, authorization); + doSubscribeReset(traceId); doNetworkAbort(traceId, authorization); } else @@ -4111,7 +4250,7 @@ private void onSubscribeData( { droppedHandler.accept(data.typeId(), data.buffer(), data.offset(), data.sizeof()); } - doSubscribeWindow(traceId, authorization, encodeSlotOffset, encodeBudgetMax); + doSubscribeWindow(traceId, encodeSlotOffset, encodeBudgetMax); } } @@ -4131,7 +4270,7 @@ private void onSubscribeReset( // } decodeNetwork(traceId); - cleanupAbort(traceId, authorization); + cleanupAbort(traceId); } private void onSubscribeWindow( @@ -4147,16 +4286,7 @@ private void onSubscribeWindow( if (!subscriptions.isEmpty() && !adminSubscribe) { - final byte[] subscriptionPayload = new byte[subscriptions.size()]; - //TODO: if we get back the window, can it be anything else than success? I think yes, and we only need to - // recognize reject scenarios when doing the decodeSubscribe - for (int i = 0; i < subscriptionPayload.length; i++) - { - subscriptionPayload[i] = SUCCESS; - } - - doEncodeSuback(traceId, authorization, packetId, subscriptionPayload); - if (session && !sessionStream.deferredUnsubscribes.isEmpty()) + if (!sessionStream.deferredUnsubscribes.isEmpty()) { Iterator>> iterator = sessionStream.deferredUnsubscribes.entrySet().iterator(); @@ -4174,7 +4304,7 @@ private void onSubscribeWindow( iterator.remove(); } - sendNewSessionStateForUnsubscribe(traceId, authorization, ackedTopicFilters); + doSendSessionState(traceId, ackedTopicFilters); } } @@ -4201,7 +4331,7 @@ private void onSubscribeWindow( if (MqttState.initialClosing(state) && !MqttState.initialClosed(state)) { - doSubscribeAppEnd(traceId, authorization); + doSubscribeAppEnd(traceId); } } @@ -4225,29 +4355,19 @@ private void onSubscribeAbort( final long traceId = abort.traceId(); final long authorization = abort.authorization(); - cleanupAbort(traceId, authorization); + cleanupAbort(traceId); } private void cleanupAbort( - long traceId, - long authorization) + long traceId) { - doSubscribeAbort(traceId, authorization); - doSubscribeReset(traceId, authorization); - } - - private void cleanupEnd( - long traceId, - long authorization) - { - doSubscribeNetEnd(traceId, authorization); - doSubscribeAppEnd(traceId, authorization); + doSubscribeAbort(traceId); + doSubscribeReset(traceId); } private void doSubscribeWindow( long traceId, - long authorization, int minReplyNoAck, int minReplyMax) { @@ -4263,13 +4383,12 @@ private void doSubscribeWindow( state = MqttState.openReply(state); doWindow(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, encodeBudgetId, PUBLISH_FRAMING); + traceId, sessionId, encodeBudgetId, PUBLISH_FRAMING); } } private void doSubscribeReset( - long traceId, - long authorization) + long traceId) { if (!MqttState.replyClosed(state)) { @@ -4279,39 +4398,17 @@ private void doSubscribeReset( setSubscribeAppClosed(); doReset(application, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, EMPTY_OCTETS); + traceId, sessionId, EMPTY_OCTETS); } } private void doSubscribeAppEnd( - long traceId, - long authorization) + long traceId) { if (MqttState.initialOpening(state) && !MqttState.initialClosed(state)) { - setNetClosed(); - subscribeStreams.remove(clientKey); - doEnd(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, EMPTY_OCTETS); - } - } - - private void setSubscribeNetClosed() - { - assert !MqttState.initialClosed(state); - - state = MqttState.closeInitial(state); - - if (debitorIndex != NO_DEBITOR_INDEX) - { - debitor.release(debitorIndex, initialId); - debitorIndex = NO_DEBITOR_INDEX; - } - - if (MqttState.closed(state)) - { - subscribeStreams.remove(clientKey); + traceId, sessionId, EMPTY_OCTETS); } } @@ -4320,7 +4417,7 @@ private void setSubscribeAppClosed() { if (MqttState.closed(state)) { - subscribeStreams.remove(clientKey); + subscribeStreams.remove(routedId); } } @@ -4333,6 +4430,30 @@ private static boolean invalidWillQos( return (flags & WILL_QOS_MASK) == WILL_QOS_MASK; } + private static boolean retainAvailable( + int capabilities) + { + return (capabilities & RETAIN_AVAILABLE_MASK) != 0; + } + + private static boolean wildcardAvailable( + int capabilities) + { + return (capabilities & WILDCARD_AVAILABLE_MASK) != 0; + } + + private static boolean subscriptionIdsAvailable( + int capabilities) + { + return (capabilities & SUBSCRIPTION_IDS_AVAILABLE_MASK) != 0; + } + + private static boolean sharedSubscriptionAvailable( + int capabilities) + { + return (capabilities & SHARED_SUBSCRIPTIONS_AVAILABLE_MASK) != 0; + } + private static boolean isSetWillQos( int flags) { @@ -4458,16 +4579,6 @@ private static int decodeConnectFlags( return reasonCode; } - private static DirectBuffer copyBuffer( - DirectBuffer buffer, - int index, - int length) - { - UnsafeBuffer copy = new UnsafeBuffer(new byte[length]); - copy.putBytes(0, buffer, index, length); - return copy; - } - private final class MqttConnectPayload { private byte reasonCode = SUCCESS; @@ -4524,21 +4635,11 @@ private int decode( break decode; } final byte qos = (byte) ((flags & WILL_QOS_MASK) >>> 3); - if (qos != 0 && qos <= maximumQos) + if (qos != 0) { willQos = (byte) (qos << 1); } - if (isSetWillRetain(flags)) - { - if (retainedMessages == 0) - { - reasonCode = RETAIN_NOT_SUPPORTED; - break decode; - } - willRetain = (byte) RETAIN_FLAG; - } - willProperties = mqttWill.properties(); decode(willProperties); @@ -4696,90 +4797,80 @@ private int decode( qos = calculatePublishApplicationQos(typeAndFlags); int alias = 0; - if (qos > maximumQos) - { - reasonCode = QOS_NOT_SUPPORTED; - } - else if (retained && retainedMessages == 0) - { - reasonCode = RETAIN_NOT_SUPPORTED; - } - else + + decode: + for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) { - decode: - for (int decodeProgress = decodeOffset; decodeProgress < decodeLimit; ) + final MqttPropertyFW mqttProperty = mqttPropertyRO.wrap(decodeBuffer, decodeProgress, decodeLimit); + switch (mqttProperty.kind()) { - final MqttPropertyFW mqttProperty = mqttPropertyRO.wrap(decodeBuffer, decodeProgress, decodeLimit); - switch (mqttProperty.kind()) + case KIND_EXPIRY_INTERVAL: + expiryInterval = mqttProperty.expiryInterval(); + break; + case KIND_CONTENT_TYPE: + final String16FW mContentType = mqttProperty.contentType(); + if (mContentType.value() != null) { - case KIND_EXPIRY_INTERVAL: - expiryInterval = mqttProperty.expiryInterval(); - break; - case KIND_CONTENT_TYPE: - final String16FW mContentType = mqttProperty.contentType(); - if (mContentType.value() != null) - { - final int offset = mContentType.offset(); - final int limit = mContentType.limit(); + final int offset = mContentType.offset(); + final int limit = mContentType.limit(); - contentType = contentTypeRO.wrap(mContentType.buffer(), offset, limit); - } - break; - case KIND_TOPIC_ALIAS: - if (alias != 0) - { - reasonCode = PROTOCOL_ERROR; - break decode; - } + contentType = contentTypeRO.wrap(mContentType.buffer(), offset, limit); + } + break; + case KIND_TOPIC_ALIAS: + if (alias != 0) + { + reasonCode = PROTOCOL_ERROR; + break decode; + } - alias = mqttProperty.topicAlias() & 0xFFFF; + alias = mqttProperty.topicAlias() & 0xFFFF; - if (alias <= 0 || alias > server.topicAliasMaximum) - { - reasonCode = TOPIC_ALIAS_INVALID; - break decode; - } + if (alias <= 0 || alias > server.topicAliasMaximum) + { + reasonCode = TOPIC_ALIAS_INVALID; + break decode; + } - if (topic.isEmpty()) - { - if (!server.topicAliases.containsKey(alias)) - { - reasonCode = PROTOCOL_ERROR; - break decode; - } - topic = server.topicAliases.get(alias); - } - else + if (topic.isEmpty()) + { + if (!server.topicAliases.containsKey(alias)) { - server.topicAliases.put(alias, topic); + reasonCode = PROTOCOL_ERROR; + break decode; } - break; - case KIND_PAYLOAD_FORMAT: - payloadFormat = MqttPayloadFormat.valueOf(mqttProperty.payloadFormat()); - break; - case KIND_RESPONSE_TOPIC: - final String16FW mResponseTopic = mqttProperty.responseTopic(); - if (mResponseTopic.value() != null) - { - final int offset = mResponseTopic.offset(); - final int limit = mResponseTopic.limit(); + topic = server.topicAliases.get(alias); + } + else + { + server.topicAliases.put(alias, topic); + } + break; + case KIND_PAYLOAD_FORMAT: + payloadFormat = MqttPayloadFormat.valueOf(mqttProperty.payloadFormat()); + break; + case KIND_RESPONSE_TOPIC: + final String16FW mResponseTopic = mqttProperty.responseTopic(); + if (mResponseTopic.value() != null) + { + final int offset = mResponseTopic.offset(); + final int limit = mResponseTopic.limit(); - responseTopic = responseTopicRO.wrap(mResponseTopic.buffer(), offset, limit); - } - break; - case KIND_CORRELATION_DATA: - correlationData = mqttProperty.correlationData().bytes(); - break; - case KIND_USER_PROPERTY: - final MqttUserPropertyFW userProperty = mqttProperty.userProperty(); - userPropertiesRW.item(c -> c.key(userProperty.key()).value(userProperty.value())); - break; - default: - reasonCode = MALFORMED_PACKET; - break decode; + responseTopic = responseTopicRO.wrap(mResponseTopic.buffer(), offset, limit); } - decodeProgress = mqttProperty.limit(); + break; + case KIND_CORRELATION_DATA: + correlationData = mqttProperty.correlationData().bytes(); + break; + case KIND_USER_PROPERTY: + final MqttUserPropertyFW userProperty = mqttProperty.userProperty(); + userPropertiesRW.item(c -> c.key(userProperty.key()).value(userProperty.value())); + break; + default: + reasonCode = MALFORMED_PACKET; + break decode; } + decodeProgress = mqttProperty.limit(); } } @@ -4813,5 +4904,21 @@ private int calculatePublishApplicationFlags( return flags; } } + + private GuardHandler resolveGuard( + MqttOptionsConfig options, + ToLongFunction resolveId) + { + GuardHandler guard = null; + + if (options != null && + options.authorization != null) + { + long guardId = resolveId.applyAsLong(options.authorization.name); + guard = supplyGuard.apply(guardId); + } + + return guard; + } } diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttState.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttState.java similarity index 100% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttState.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttState.java diff --git a/incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttStreamFactory.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttStreamFactory.java similarity index 100% rename from incubator/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttStreamFactory.java rename to runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttStreamFactory.java diff --git a/runtime/binding-mqtt/src/main/moditect/module-info.java b/runtime/binding-mqtt/src/main/moditect/module-info.java new file mode 100644 index 0000000000..4cf09438f0 --- /dev/null +++ b/runtime/binding-mqtt/src/main/moditect/module-info.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +module io.aklivity.zilla.runtime.binding.mqtt +{ + requires io.aklivity.zilla.runtime.engine; + + exports io.aklivity.zilla.runtime.binding.mqtt.config; + + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi + with io.aklivity.zilla.runtime.binding.mqtt.internal.MqttBindingFactorySpi; + + provides io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi + with io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttOptionsConfigAdapter; + + provides io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi + with io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttConditionConfigAdapter; +} diff --git a/incubator/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi b/runtime/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi similarity index 100% rename from incubator/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi rename to runtime/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi diff --git a/incubator/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi b/runtime/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi similarity index 100% rename from incubator/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi rename to runtime/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi diff --git a/runtime/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi b/runtime/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi new file mode 100644 index 0000000000..9ef2b8ec8c --- /dev/null +++ b/runtime/binding-mqtt/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi @@ -0,0 +1 @@ +io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttOptionsConfigAdapter diff --git a/incubator/binding-mqtt/src/main/zilla/protocol.idl b/runtime/binding-mqtt/src/main/zilla/protocol.idl similarity index 100% rename from incubator/binding-mqtt/src/main/zilla/protocol.idl rename to runtime/binding-mqtt/src/main/zilla/protocol.idl diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfigurationTest.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfigurationTest.java similarity index 80% rename from incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfigurationTest.java rename to runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfigurationTest.java index 3c1b813f58..d1669a24d6 100644 --- a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfigurationTest.java +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttConfigurationTest.java @@ -23,13 +23,12 @@ import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.NO_LOCAL; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.RETAIN_AVAILABLE; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SESSIONS_AVAILABLE; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SESSION_EXPIRY_GRACE_PERIOD; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SESSION_EXPIRY_INTERVAL; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SHARED_SUBSCRIPTION_AVAILABLE; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SUBSCRIPTION_IDENTIFIERS_AVAILABLE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SHARED_SUBSCRIPTION; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SUBSCRIPTION_ID; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.SUBSCRIPTION_IDENTIFIERS; import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.TOPIC_ALIAS_MAXIMUM; -import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.WILDCARD_SUBSCRIPTION_AVAILABLE; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.WILDCARD_SUBSCRIPTION; import static org.junit.Assert.assertEquals; import org.junit.Test; @@ -38,7 +37,6 @@ public class MqttConfigurationTest { public static final String PUBLISH_TIMEOUT_NAME = "zilla.binding.mqtt.publish.timeout"; public static final String CONNECT_TIMEOUT_NAME = "zilla.binding.mqtt.connect.timeout"; - public static final String SESSION_EXPIRY_INTERVAL_NAME = "zilla.binding.mqtt.session.expiry.interval"; public static final String KEEP_ALIVE_MINIMUM_NAME = "zilla.binding.mqtt.keep.alive.minimum"; public static final String KEEP_ALIVE_MAXIMUM_NAME = "zilla.binding.mqtt.keep.alive.maximum"; public static final String MAXIMUM_QOS_NAME = "zilla.binding.mqtt.maximum.qos"; @@ -47,28 +45,27 @@ public class MqttConfigurationTest public static final String WILDCARD_SUBSCRIPTION_AVAILABLE_NAME = "zilla.binding.mqtt.wildcard.subscription.available"; public static final String SUBSCRIPTION_IDENTIFIERS_AVAILABLE_NAME = "zilla.binding.mqtt.subscription.identifiers.available"; public static final String SHARED_SUBSCRIPTION_AVAILABLE_NAME = "zilla.binding.mqtt.shared.subscription.available"; - public static final String SESSION_AVAILABLE_NAME = "zilla.binding.mqtt.sessions.available"; public static final String NO_LOCAL_NAME = "zilla.binding.mqtt.no.local"; public static final String SESSION_EXPIRY_GRACE_PERIOD_NAME = "zilla.binding.mqtt.session.expiry.grace.period"; public static final String CLIENT_ID_NAME = "zilla.binding.mqtt.client.id"; + public static final String SUBSCRIPTION_ID_NAME = "zilla.binding.mqtt.subscription.id"; @Test - public void shouldVerifyConstants() throws Exception + public void shouldVerifyConstants() { assertEquals(PUBLISH_TIMEOUT.name(), PUBLISH_TIMEOUT_NAME); assertEquals(CONNECT_TIMEOUT.name(), CONNECT_TIMEOUT_NAME); - assertEquals(SESSION_EXPIRY_INTERVAL.name(), SESSION_EXPIRY_INTERVAL_NAME); assertEquals(KEEP_ALIVE_MINIMUM.name(), KEEP_ALIVE_MINIMUM_NAME); assertEquals(KEEP_ALIVE_MAXIMUM.name(), KEEP_ALIVE_MAXIMUM_NAME); assertEquals(MAXIMUM_QOS.name(), MAXIMUM_QOS_NAME); assertEquals(RETAIN_AVAILABLE.name(), RETAIN_AVAILABLE_NAME); assertEquals(TOPIC_ALIAS_MAXIMUM.name(), TOPIC_ALIAS_MAXIMUM_NAME); - assertEquals(WILDCARD_SUBSCRIPTION_AVAILABLE.name(), WILDCARD_SUBSCRIPTION_AVAILABLE_NAME); - assertEquals(SUBSCRIPTION_IDENTIFIERS_AVAILABLE.name(), SUBSCRIPTION_IDENTIFIERS_AVAILABLE_NAME); - assertEquals(SHARED_SUBSCRIPTION_AVAILABLE.name(), SHARED_SUBSCRIPTION_AVAILABLE_NAME); - assertEquals(SESSIONS_AVAILABLE.name(), SESSION_AVAILABLE_NAME); + assertEquals(WILDCARD_SUBSCRIPTION.name(), WILDCARD_SUBSCRIPTION_AVAILABLE_NAME); + assertEquals(SUBSCRIPTION_IDENTIFIERS.name(), SUBSCRIPTION_IDENTIFIERS_AVAILABLE_NAME); + assertEquals(SHARED_SUBSCRIPTION.name(), SHARED_SUBSCRIPTION_AVAILABLE_NAME); assertEquals(NO_LOCAL.name(), NO_LOCAL_NAME); assertEquals(SESSION_EXPIRY_GRACE_PERIOD.name(), SESSION_EXPIRY_GRACE_PERIOD_NAME); assertEquals(CLIENT_ID.name(), CLIENT_ID_NAME); + assertEquals(SUBSCRIPTION_ID.name(), SUBSCRIPTION_ID_NAME); } } diff --git a/incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/ValidatorTest.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/ValidatorTest.java similarity index 100% rename from incubator/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/ValidatorTest.java rename to runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/ValidatorTest.java diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapterTest.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapterTest.java new file mode 100644 index 0000000000..730334c0ee --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttConditionConfigAdapterTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import static java.util.function.Function.identity; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; + +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; + +import org.junit.Before; +import org.junit.Test; + +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttConditionConfig; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttPublishConfig; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttSessionConfig; +import io.aklivity.zilla.runtime.binding.mqtt.config.MqttSubscribeConfig; + +public class MqttConditionConfigAdapterTest +{ + private Jsonb jsonb; + + @Before + public void initJson() + { + JsonbConfig config = new JsonbConfig() + .withAdapters(new MqttConditionConfigAdapter()); + jsonb = JsonbBuilder.create(config); + } + + @Test + public void shouldReadCondition() + { + String text = + "{" + + "\"session\":" + + "[" + + "{" + + "\"client-id\": \"*\"" + + "}" + + "]," + + "\"subscribe\":" + + "[" + + "{" + + "\"topic\": \"reply/one\"" + + "}," + + "{" + + "\"topic\": \"reply/two\"" + + "}," + + "]," + + "\"publish\":" + + "[" + + "{" + + "\"topic\": \"command/one\"" + + "}," + + "{" + + "\"topic\": \"command/two\"" + + "}" + + "]" + + "}"; + + MqttConditionConfig condition = jsonb.fromJson(text, MqttConditionConfig.class); + + assertThat(condition, not(nullValue())); + assertThat(condition.sessions, not(nullValue())); + assertThat(condition.sessions.get(0).clientId, equalTo("*")); + assertThat(condition.subscribes, not(nullValue())); + assertThat(condition.subscribes.get(0).topic, equalTo("reply/one")); + assertThat(condition.subscribes.get(1).topic, equalTo("reply/two")); + assertThat(condition.publishes, not(nullValue())); + assertThat(condition.publishes.get(0).topic, equalTo("command/one")); + assertThat(condition.publishes.get(1).topic, equalTo("command/two")); + } + + @Test + public void shouldWriteCondition() + { + MqttConditionConfig condition = MqttConditionConfig.builder() + .inject(identity()) + .session(new MqttSessionConfig("*")) + .subscribe(new MqttSubscribeConfig("reply/one")) + .subscribe(new MqttSubscribeConfig("reply/two")) + .publish(new MqttPublishConfig("command/one")) + .publish(new MqttPublishConfig("command/two")) + .build(); + + String text = jsonb.toJson(condition); + + assertThat(text, not(nullValue())); + assertThat(text, equalTo("{\"session\":[{\"client-id\":\"*\"}],\"subscribe\":[{\"topic\":\"reply/one\"}," + + "{\"topic\":\"reply/two\"}],\"publish\":[{\"topic\":\"command/one\"},{\"topic\":\"command/two\"}]}")); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfigAdapterTest.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfigAdapterTest.java new file mode 100644 index 0000000000..85a208afd7 --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/config/MqttOptionsConfigAdapterTest.java @@ -0,0 +1,115 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.config; + +import static java.util.Collections.singletonList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; + +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; + +import org.junit.Before; +import org.junit.Test; + +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttCredentialsConfig; +import io.aklivity.zilla.runtime.binding.mqtt.internal.config.MqttAuthorizationConfig.MqttPatternConfig; + +public class MqttOptionsConfigAdapterTest +{ + private Jsonb jsonb; + + @Before + public void initJson() + { + JsonbConfig config = new JsonbConfig() + .withAdapters(new MqttOptionsConfigAdapter()); + jsonb = JsonbBuilder.create(config); + } + + @Test + public void shouldReadOptions() + { + String text = + "{" + + "\"authorization\":" + + "{" + + "\"test0\":" + + "{" + + "\"credentials\":" + + "{" + + "\"connect\":" + + "{" + + "\"username\":\"Bearer {credentials}\"" + + "}" + + "}" + + "}" + + "}," + + "}"; + + MqttOptionsConfig options = jsonb.fromJson(text, MqttOptionsConfig.class); + + assertThat(options, not(nullValue())); + assertThat(options.authorization, not(nullValue())); + assertThat(options.authorization.name, equalTo("test0")); + assertThat(options.authorization.credentials, not(nullValue())); + assertThat(options.authorization.credentials.connect, not(nullValue())); + assertThat(options.authorization.credentials.connect, hasSize(1)); + assertThat(options.authorization.credentials.connect.get(0), not(nullValue())); + assertThat(options.authorization.credentials.connect.get(0).property, + equalTo(MqttAuthorizationConfig.MqttConnectProperty.USERNAME)); + assertThat(options.authorization.credentials.connect.get(0).pattern, + equalTo("Bearer {credentials}")); + + } + + @Test + public void shouldWriteOptions() + { + MqttOptionsConfig options = new MqttOptionsConfig( + new MqttAuthorizationConfig( + "test0", + new MqttCredentialsConfig( + singletonList(new MqttPatternConfig( + MqttAuthorizationConfig.MqttConnectProperty.USERNAME, + "Bearer {credentials}"))))); + + String text = jsonb.toJson(options); + + assertThat(text, not(nullValue())); + assertThat(text, equalTo( + "{" + + + "\"authorization\":" + + "{" + + "\"test0\":" + + "{" + + "\"credentials\":" + + "{" + + "\"connect\":" + + "{" + + "\"username\":\"Bearer {credentials}\"" + + "}" + + "}" + + "}" + + "}" + + "}")); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/ConnectionIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/ConnectionIT.java new file mode 100644 index 0000000000..502ba2304a --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/ConnectionIT.java @@ -0,0 +1,113 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.client; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class ConnectionIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/client.sent.abort/server", + "${app}/client.sent.abort/client"}) + public void shouldReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/session.will.message.retain/server", + "${app}/session.will.message.retain/client"}) + public void shouldConnectWithWillMessageRetain() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/connect.non.successful.connack/server", + "${app}/connect.non.successful.connack/client"}) + public void shouldResetWithReasonCodeOnNonSuccessfulConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/connect.non.successful.disconnect/server", + "${app}/connect.non.successful.disconnect/client"}) + public void shouldResetWithReasonCodeOnNonSuccessfulDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/disconnect.after.subscribe.and.publish/server", + "${app}/disconnect.after.subscribe.and.publish/client"}) + public void shouldDisconnectAfterSubscribeAndPublish() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/connect.delegate.connack.properties/server", + "${app}/connect.delegate.connack.properties/client"}) + public void shouldDelegateConnackProperties() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/PingIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/PingIT.java new file mode 100644 index 0000000000..cf35834032 --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/PingIT.java @@ -0,0 +1,77 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.client; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class PingIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/ping.server.override.keep.alive/server", + "${app}/session.connect/client"}) + public void shouldConnectThenPingRequestResponse() throws Exception + { + k3po.start(); + Thread.sleep(2500); + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/ping.no.pingresp/server", + "${app}/session.connect.abort/client"}) + public void shouldCloseWhenPingRequestNoResponseInTimeout() throws Exception + { + k3po.start(); + Thread.sleep(2000); + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/PublishIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/PublishIT.java new file mode 100644 index 0000000000..69b5195bfc --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/PublishIT.java @@ -0,0 +1,135 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.client; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class PublishIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + + //TODO: adapt this once we decided + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.empty.message/server", + "${app}/publish.empty.message/client"}) + public void shouldSendEmptyMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.empty.retained.message/server", + "${app}/publish.empty.retained.message/client"}) + public void shouldSendEmptyRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.multiple.messages/server", + "${app}/publish.multiple.messages/client"}) + public void shouldSendMultipleMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.one.message/server", + "${app}/publish.one.message/client"}) + public void shouldSendOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.retained/server", + "${app}/publish.retained/client"}) + public void shouldPublishRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.with.user.properties.distinct/server", + "${app}/publish.with.user.properties.distinct/client"}) + public void shouldSendWithDistinctUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.with.user.properties.repeated/server", + "${app}/publish.with.user.properties.repeated/client"}) + public void shouldSendWithRepeatedUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/publish.with.user.property/server", + "${app}/publish.with.user.property/client"}) + public void shouldSendWithUserProperty() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/SubscribeIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/SubscribeIT.java new file mode 100644 index 0000000000..5fedfc1ec4 --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/SubscribeIT.java @@ -0,0 +1,322 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.client; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class SubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/session.subscribe/server", + "${app}/session.subscribe/client"}) + public void shouldSubscribe() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.one.message/server", + "${app}/subscribe.one.message/client"}) + public void shouldReceiveOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.retain.as.published/server", + "${app}/subscribe.retain.as.published/client"}) + public void shouldReceiveRetainAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.one.message.receive.response.topic.and.correlation.data/server", + "${app}/subscribe.one.message.receive.response.topic.and.correlation.data/client"}) + public void shouldReceiveCorrelationData() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.one.message.user.properties.unaltered/server", + "${app}/subscribe.one.message.user.properties.unaltered/client"}) + public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.publish.no.local/server", + "${app}/subscribe.publish.no.local/client"}) + public void shouldNotReceivePublishLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.qos0.publish.retained.no.replay/server", + "${app}/subscribe.qos0.publish.retained.no.replay/client"}) + public void shouldNotReplayRetained() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.qos0.replay.retained.no.packet.id/server", + "${app}/subscribe.qos0.replay.retained.no.packet.id/client"}) + public void shouldReceiveAndReplayRetainedQos0() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.receive.message/server", + "${app}/subscribe.receive.message/client"}) + public void shouldReceiveOneMessageAfterPublish() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.receive.messages.topic.alias.repeated/server", + "${app}/subscribe.receive.messages.topic.alias.repeated/client"}) + public void shouldReceiveMessagesTopicAliasRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.receive.message.overlapping.wildcard/server", + "${app}/subscribe.receive.message.overlapping.wildcard/client"}) + public void shouldReceiveMessageOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.receive.message.wildcard/server", + "${app}/subscribe.receive.message.wildcard/client"}) + public void shouldReceiveOneMessageWithPatternTopic() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filter.multi.level.wildcard/server", + "${app}/subscribe.topic.filter.multi.level.wildcard/client"}) + public void shouldFilterMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filter.single.and.multi.level.wildcard/server", + "${app}/subscribe.topic.filter.single.and.multi.level.wildcard/client"}) + public void shouldFilterSingleAndMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filter.single.exact/server", + "${app}/subscribe.topic.filter.single.exact/client"}) + public void shouldFilterExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filter.two.single.level.wildcard/server", + "${app}/subscribe.topic.filter.two.single.level.wildcard/client"}) + public void shouldFilterTwoSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.aggregated.both.exact/server", + "${app}/subscribe.topic.filters.aggregated.both.exact/client"}) + public void shouldFilterAggregatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.aggregated.exact.and.wildcard/server", + "${app}/subscribe.topic.filters.aggregated.exact.and.wildcard/client"}) + public void shouldFilterAggregatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filter.single.level.wildcard/server", + "${app}/subscribe.topic.filter.single.level.wildcard/client"}) + public void shouldFilterSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.disjoint.wildcards/server", + "${app}/subscribe.topic.filters.disjoint.wildcards/client"}) + public void shouldFilterDisjointWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.exact/server", + "${app}/subscribe.topic.filters.isolated.both.exact/client"}) + public void shouldFilterIsolatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.wildcard/server", + "${app}/subscribe.topic.filters.isolated.both.wildcard/client"}) + public void shouldFilterIsolatedBothWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.isolated.exact.and.wildcard/server", + "${app}/subscribe.topic.filters.isolated.exact.and.wildcard/client"}) + public void shouldFilterIsolatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.overlapping.wildcards/server", + "${app}/subscribe.topic.filters.overlapping.wildcards/client"}) + public void shouldFilterOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.topic.filters.non.successful/server", + "${app}/subscribe.topic.filters.non.successful/client"}) + public void shouldFilterNonSuccessful() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/subscribe.reconnect.publish.no.subscription/server", + "${app}/subscribe.reconnect.publish.no.subscription/client"}) + public void shouldReceiveReconnectNoSubscription() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${app}/subscribe.publish.invalid.affinity/client"}) + public void shouldAbortSubscribeAndPublishInvalidAffinity() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/UnsubscribeIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/UnsubscribeIT.java new file mode 100644 index 0000000000..355b6f10b1 --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/client/UnsubscribeIT.java @@ -0,0 +1,93 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.client; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class UnsubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("net0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/unsubscribe.topic.filter.single/server", + "${app}/unsubscribe.topic.filter.single/client"}) + public void shouldAcknowledgeSingleTopicFilters() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/unsubscribe.after.subscribe/server", + "${app}/unsubscribe.after.subscribe/client"}) + public void shouldAcknowledge() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/unsubscribe.aggregated.topic.filters.both.exact/server", + "${app}/unsubscribe.aggregated.topic.filters.both.exact/client"}) + public void shouldAcknowledgeAggregatedTopicFiltersBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("client.yaml") + @Specification({ + "${net}/unsubscribe.topic.filters.non.successful/server", + "${app}/unsubscribe.topic.filters.non.successful/client"}) + public void shouldAcknowledgeNonSuccessful() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/ConnectionIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/ConnectionIT.java new file mode 100644 index 0000000000..61294723de --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/ConnectionIT.java @@ -0,0 +1,491 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.server; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.CLIENT_ID_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.CONNECT_TIMEOUT_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.KEEP_ALIVE_MINIMUM_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static io.aklivity.zilla.runtime.engine.test.EngineRule.ENGINE_BUFFER_SLOT_CAPACITY_NAME; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class ConnectionIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("app0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.successful/client", + "${app}/session.connect/server"}) + public void shouldConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.credentials.username.yaml") + @Specification({ + "${net}/connect.username.authentication.successful/client", + "${app}/session.connect/server"}) + public void shouldAuthenticateUsernameAndConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.credentials.username.yaml") + @Specification({ + "${net}/connect.username.authentication.failed/client"}) + public void shouldFailUsernameAuthentication() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.credentials.password.yaml") + @Specification({ + "${net}/connect.password.authentication.successful/client", + "${app}/session.connect/server"}) + public void shouldAuthenticatePasswordAndConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.credentials.password.yaml") + @Specification({ + "${net}/connect.password.authentication.failed/client"}) + public void shouldFailPasswordAuthentication() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.server.assigned.client.id/client", + "${app}/session.connect/server"}) + @Configure(name = CLIENT_ID_NAME, value = "client") + public void shouldConnectWithServerAssignedClientId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.missing.client.id/client"}) + public void shouldRejectMissingClientId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/disconnect/client", + "${app}/session.connect/server"}) + public void shouldConnectThenDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/disconnect.no.reasoncode.no.properties/client", + "${app}/session.connect/server"}) + public void shouldConnectThenDisconnectWithNoReasonCodeNoProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/disconnect.after.subscribe.and.publish/client", + "${app}/disconnect.after.subscribe.and.publish/server"}) + public void shouldDisconnectAfterSubscribeAndPublish() throws Exception + { + k3po.finish(); + } + + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.invalid.protocol.version/client"}) + public void shouldRejectInvalidProtocolVersion() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.invalid.flags/client"}) + public void shouldRejectMalformedConnectPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.invalid.authentication.method/client"}) + public void shouldRejectBadAuthenticationMethod() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/disconnect.reject.invalid.fixed.header.flags/client", + "${app}/session.connect/server"}) + public void shouldRejectMalformedDisconnectPacket() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.0-2] + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.second.connect/client", + "${app}/session.connect/server"}) + public void shouldRejectSecondConnectPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.successful.fragmented/client", + "${app}/session.connect/server"}) + public void shouldConnectFragmented() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.0-1] + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.other.packet.before.connect/client"}) + public void shouldRejectOtherPacketBeforeConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.topic.alias.maximum.repeated/client"}) + public void shouldRejectConnectWhenTopicAliasMaximumRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/client.sent.close/client", + "${app}/client.sent.abort/server"}) + public void shouldReceiveClientSentClose() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/client.sent.abort/client", + "${app}/client.sent.abort/server"}) + public void shouldReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/client.sent.reset/client", + "${app}/client.sent.abort/server"}) + public void shouldReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/disconnect.after.keep.alive.timeout/client", + "${app}/session.connect/server"}) + @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "1") + public void shouldDisconnectClientAfterKeepAliveTimeout() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.timeout.before.connect/client"}) + @Configure(name = CONNECT_TIMEOUT_NAME, value = "1") + public void shouldTimeoutBeforeConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.maximum.qos.0/client", + "${app}/connect.maximum.qos.0/server"}) + public void shouldConnectWithMaximumQos0() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.retain.not.supported/client", + "${app}/connect.retain.not.supported/server"}) + public void shouldConnectWithRetainNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.will.retain.not.supported/client", + "${app}/connect.reject.will.retain.not.supported/server"}) + public void shouldRejectConnectWillRetainNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.password.flag.no.password/client"}) + public void shouldRejectConnectWithPasswordFlagSetNoPassword() throws Exception + { + k3po.finish(); + } + + @Ignore + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.password.no.password.flag/client"}) + public void shouldRejectConnectWithPasswordNoPasswordFlag() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.username.flag.only/client"}) + public void shouldRejectConnectWithUsernameFlagNoUsername() throws Exception + { + k3po.finish(); + } + + @Ignore + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.username.flag.missing/client"}) + public void shouldRejectConnectWithUsernameNoUsernameFlag() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.will.payload.missing/client"}) + public void shouldRejectConnectWillPayloadMissing() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.will.properties.missing/client"}) + public void shouldRejectConnectWillPropertiesMissing() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.will.topic.missing/client"}) + public void shouldRejectConnectWillTopicMissing() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.will.invalid.will.qos/client"}) + public void shouldRejectInvalidWillQos() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.will.reject.will.qos.1.without.will.flag/client"}) + public void shouldRejectWillQos1WithoutWillFlag() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.will.reject.will.qos.2.without.will.flag/client"}) + public void shouldRejectWillQos2WithoutWillFlag() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.will.reject.will.retain.without.will.flag/client"}) + public void shouldRejectWillRetainWithoutWillFlag() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.max.packet.size.exceeded/client", + "${app}/connect.max.packet.size.exceeded/server"}) + public void shouldIgnorePublishPacketBiggerThanMaxPacketSize() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.server.defined.keep.alive/client", + "${app}/session.connect/server"}) + @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "10") + public void shouldConnectWithServerDefinedKeepAlive() throws Exception + { + k3po.start(); + Thread.sleep(2000); + k3po.notifyBarrier("WAIT_2_SECONDS"); + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.subscribe.unfragmented/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + public void shouldConnectAndSubscribeUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.reject.packet.too.large/client"}) + @Configure(name = ENGINE_BUFFER_SLOT_CAPACITY_NAME, value = "8192") + public void shouldRejectPacketTooLarge() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/disconnect.invalid.session.expiry/client", + "${app}/session.connect/server"}) + public void shouldRejectInvalidSessionExpiryOnDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.non.successful.connack/client", + "${app}/connect.non.successful.connack/server"}) + public void shouldResetWithReasonCodeOnNonSuccessfulConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/connect.non.successful.disconnect/client", + "${app}/connect.non.successful.disconnect/server"}) + public void shouldResetWithReasonCodeOnNonSuccessfulDisconnect() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/PingIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/PingIT.java new file mode 100644 index 0000000000..87431e71c8 --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/PingIT.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.server; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.KEEP_ALIVE_MINIMUM_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class PingIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("app0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/ping/client", + "${app}/session.connect/server"}) + public void shouldConnectThenPingRequestResponse() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/ping.keep.alive/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "1") + public void shouldPingAtKeepAliveInterval() throws Exception + { + k3po.start(); + Thread.sleep(1000); + k3po.notifyBarrier("WAIT_1_SECOND"); + Thread.sleep(1000); + k3po.notifyBarrier("WAIT_1_SECOND2"); + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/PublishIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/PublishIT.java new file mode 100644 index 0000000000..2f60250465 --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/PublishIT.java @@ -0,0 +1,351 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.server; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.PUBLISH_TIMEOUT_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.TOPIC_ALIAS_MAXIMUM_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static io.aklivity.zilla.runtime.engine.test.EngineRule.ENGINE_BUFFER_SLOT_CAPACITY_NAME; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class PublishIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("app0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.one.message/client", + "${app}/publish.one.message/server"}) + public void shouldPublishOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.retained/client", + "${app}/publish.retained/server"}) + public void shouldPublishRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.message.with.topic.alias/client", + "${app}/publish.message.with.topic.alias/server"}) + @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") + public void shouldPublishMessageWithTopicAlias() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.multiple.messages/client", + "${app}/publish.multiple.messages/server"}) + public void shouldPublishMultipleMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.multiple.messages.unfragmented/client", + "${app}/publish.multiple.messages/server"}) + public void shouldPublishMultipleMessagesUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.one.message.subscribe.unfragmented/client", + "${app}/publish.one.message.subscribe.unfragmented/server"}) + public void shouldPublishOneMessageSubscribeUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.multiple.messages.with.delay/client", + "${app}/publish.multiple.messages/server"}) + @Configure(name = PUBLISH_TIMEOUT_NAME, value = "5") + public void shouldPublishMultipleMessagesWithDelay() throws Exception + { + k3po.start(); + k3po.awaitBarrier("PUBLISHED_MESSAGE_TWO"); + Thread.sleep(500); + k3po.notifyBarrier("PUBLISH_MESSAGE_THREE"); + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.messages.with.topic.alias.distinct/client", + "${app}/publish.messages.with.topic.alias.distinct/server"}) + @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") + public void shouldPublishMessagesWithTopicAliasDistinct() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.messages.with.topic.alias.repeated/client", + "${app}/publish.messages.with.topic.alias.repeated/server"}) + @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") + public void shouldPublishMessagesWithTopicAliasRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.messages.with.topic.alias.replaced/client", + "${app}/publish.messages.with.topic.alias.replaced/server"}) + @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "1") + public void shouldPublishMessagesWithTopicAliasReplaced() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.messages.with.topic.alias.invalid.scope/client", + "${app}/publish.messages.with.topic.alias.invalid.scope/server"}) + @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "1") + public void shouldSendMessagesWithTopicAliasInvalidScope() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.topic.not.routed/client", + "${app}/session.connect/server"}) + public void shouldRejectTopicNotRouted() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.topic.alias.exceeds.maximum/client", + "${app}/session.connect/server"}) + public void shouldRejectPublishWhenTopicAliasExceedsMaximum() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.topic.alias.repeated/client", + "${app}/session.connect/server"}) + @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") + public void shouldRejectPublishWithMultipleTopicAliases() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.client.sent.subscription.id/client", + "${app}/session.connect/server"}) + @Configure(name = TOPIC_ALIAS_MAXIMUM_NAME, value = "2") + public void shouldRejectPublishClientSentSubscriptionId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.invalid.payload.format/client", + "${app}/session.connect/server"}) + public void shouldRejectPublishInvalidPayloadFormat() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.qos1.not.supported/client", + "${app}/publish.reject.qos.not.supported/server"}) + public void shouldRejectPublishQos1NotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.qos2.not.supported/client", + "${app}/publish.reject.qos.not.supported/server"}) + public void shouldRejectPublishQos2NotSupported() throws Exception + { + k3po.finish(); + } + + @Ignore + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.qos0.with.packet.id/client"}) + public void shouldRejectPublishQos0WithPacketId() throws Exception + { + k3po.finish(); + } + + @Ignore + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.qos1.without.packet.id/client"}) + public void shouldRejectPublishQos1WithoutPacketId() throws Exception + { + k3po.finish(); + } + + @Ignore + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.qos2.without.packet.id/client"}) + public void shouldRejectPublishQos2WithoutPacketId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.retain.not.supported/client", + "${app}/publish.reject.retain.not.supported/server"}) + public void shouldRejectPublishRetainNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.with.user.property/client", + "${app}/publish.with.user.property/server"}) + public void shouldPublishWithUserProperty() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.with.user.properties.distinct/client", + "${app}/publish.with.user.properties.distinct/server"}) + public void shouldPublishWithDistinctUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.with.user.properties.repeated/client", + "${app}/publish.with.user.properties.repeated/server"}) + public void shouldPublishWithRepeatedUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.empty.retained.message/client", + "${app}/publish.empty.retained.message/server"}) + public void shouldPublishEmptyRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.empty.message/client", + "${app}/publish.empty.message/server"}) + public void shouldPublishEmptyMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.reject.packet.too.large/client", + "${app}/publish.reject.packet.too.large/server"}) + @Configure(name = ENGINE_BUFFER_SLOT_CAPACITY_NAME, value = "8192") + public void shouldRejectPacketTooLarge() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/SessionIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/SessionIT.java new file mode 100644 index 0000000000..4b0c9ca57b --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/SessionIT.java @@ -0,0 +1,248 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.server; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.KEEP_ALIVE_MINIMUM_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class SessionIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("app0") + .external("app1") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.connect.with.session.expiry/client", + "${app}/session.connect.with.session.expiry/server"}) + public void shouldConnectWithSessionExpiry() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.connect.override.session.expiry/client", + "${app}/session.connect.override.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiry() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.subscribe/client", + "${app}/session.subscribe/server"}) + public void shouldSubscribeSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.subscribe.multiple.isolated/client", + "${app}/session.subscribe.multiple.isolated/server"}) + public void shouldSubscribeMultipleSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.subscribe.via.session.state/client", + "${app}/session.subscribe.via.session.state/server"}) + public void shouldSubscribeViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.unsubscribe.after.subscribe/client", + "${app}/session.unsubscribe.after.subscribe/server"}) + public void shouldUnsubscribeSaveNewSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.unsubscribe.after.subscribe.deferred/client", + "${app}/session.unsubscribe.after.subscribe.deferred/server"}) + public void shouldUnsubscribeAfterSubscribeDeferred() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.subscribe/client", + "${app}/session.unsubscribe.via.session.state/server"}) + public void shouldUnsubscribeViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.will.message.retain/client", + "${app}/session.will.message.retain/server"}) + public void shouldStoreWillMessageInSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.connect.payload.fragmented/client", + "${app}/session.will.message.retain/server"}) + public void shouldStoreWillMessageInSessionStatePayloadFragmented() throws Exception + { + k3po.finish(); + } + + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.will.message.normal.disconnect/client", + "${app}/session.will.message.normal.disconnect/server"}) + public void shouldCloseSessionNormalDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.will.message.disconnect.with.will.message/client", + "${app}/session.will.message.abort/server"}) + public void shouldCloseSessionDisconnectWithWill() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.will.message.no.ping.within.keep.alive/client", + "${app}/session.will.message.abort/server"}) + @Configure(name = KEEP_ALIVE_MINIMUM_NAME, value = "1") + public void shouldCloseSessionWithKeepAliveExpired() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.exists.clean.start/client", + "${app}/session.exists.clean.start/server"}) + public void shouldCloseExistingConnectionCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.abort.reconnect.non.clean.start/client", + "${app}/session.abort.reconnect.non.clean.start/server"}) + public void shouldClientAbortAndReconnectWithNonCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.client.takeover/client", + "${app}/session.client.takeover/server"}) + public void shouldClientTakeOverSession() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.server.redirect.after.connack/client", + "${app}/session.server.redirect.after.connack/server"}) + public void shouldRedirectAfterConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/session.server.redirect.before.connack/client", + "${app}/session.server.redirect.before.connack/server"}) + public void shouldRedirectBeforeConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.route.non.default.yaml") + @Specification({ + "${net}/session.subscribe.publish.routing/client", + "${app}/session.subscribe.publish.routing/server"}) + public void shouldSubscribeAndPublishToNonDefaultRoute() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/SubscribeIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/SubscribeIT.java new file mode 100644 index 0000000000..7faaebd55c --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/SubscribeIT.java @@ -0,0 +1,384 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.server; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.NO_LOCAL_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfigurationTest.SUBSCRIPTION_ID_NAME; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; +import io.aklivity.zilla.runtime.engine.test.annotation.Configure; + +public class SubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configure(SUBSCRIPTION_ID_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.internal.stream.server.SubscribeIT::supplySubscriptionId") + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("app0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.one.message/client", + "${app}/subscribe.one.message/server"}) + public void shouldReceiveOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.one.message.receive.response.topic.and.correlation.data/client", + "${app}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) + public void shouldReceiveCorrelationData() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.one.message.user.properties.unaltered/client", + "${app}/subscribe.one.message.user.properties.unaltered/server"}) + public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.one.message.with.invalid.subscription.id/client", + "${app}/session.connect/server"}) + public void shouldReceiveOneMessageWithInvalidSubscriptionId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filter.single.exact/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + public void shouldFilterExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filter.multi.level.wildcard/client", + "${app}/subscribe.topic.filter.multi.level.wildcard/server"}) + public void shouldFilterMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filter.single.and.multi.level.wildcard/client", + "${app}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) + public void shouldFilterSingleAndMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filter.single.level.wildcard/client", + "${app}/subscribe.topic.filter.single.level.wildcard/server"}) + public void shouldFilterSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filter.two.single.level.wildcard/client", + "${app}/subscribe.topic.filter.two.single.level.wildcard/server"}) + public void shouldFilterTwoSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.aggregated.both.exact/client", + "${app}/subscribe.topic.filters.aggregated.both.exact/server"}) + public void shouldFilterAggregatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.exact/client", + "${app}/subscribe.topic.filters.isolated.both.exact/server"}) + public void shouldFilterIsolatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.exact.no.subscription.id/client", + "${app}/subscribe.topic.filters.isolated.both.exact/server"}) + public void shouldFilterIsolatedBothExactNoSubscriptionId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.wildcard/client", + "${app}/subscribe.topic.filters.isolated.both.wildcard/server"}) + public void shouldFilterIsolatedBothWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", + "${app}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) + public void shouldFilterAggregatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.disjoint.wildcards/client", + "${app}/subscribe.topic.filters.disjoint.wildcards/server"}) + public void shouldFilterDisjointWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.isolated.exact.and.wildcard/client", + "${app}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) + public void shouldFilterIsolatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.overlapping.wildcards/client", + "${app}/subscribe.topic.filters.overlapping.wildcards/server"}) + public void shouldFilterOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.get.retained.as.published/client", + "${app}/subscribe.get.retained.as.published/server"}) + public void shouldReceiveRetainedAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.qos0.publish.retained.no.replay/client", + "${app}/subscribe.qos0.publish.retained.no.replay/server"}) + public void shouldNotReplayRetained() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.qos0.replay.retained.no.packet.id/client", + "${app}/subscribe.qos0.replay.retained.no.packet.id/server"}) + public void shouldReceiveAndReplayRetainedQos0() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.reject.no.local/client", + "${app}/session.connect/server"}) + @Configure(name = NO_LOCAL_NAME, value = "false") + public void shouldRejectNoLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.receive.message/client", + "${app}/subscribe.receive.message/server"}) + public void shouldReceiveOneMessageAfterPublish() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.receive.message.overlapping.wildcard/client", + "${app}/subscribe.receive.message.overlapping.wildcard/server"}) + public void shouldReceiveMessageOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.receive.message.wildcard/client", + "${app}/subscribe.receive.message.wildcard/server"}) + public void shouldReceiveOneMessageWithPatternTopic() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.retain.as.published/client", + "${app}/subscribe.retain.as.published/server"}) + public void shouldReceiveRetainAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.publish.no.local/client", + "${app}/subscribe.publish.no.local/server"}) + public void shouldNotReceivePublishLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.invalid.fixed.header.flags/client", + "${app}/session.connect/server"}) + public void shouldRejectMalformedPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.invalid.topic.filter/client", + "${app}/session.connect/server"}) + public void shouldRejectInvalidTopicFilter() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.reject.wildcard.subscriptions.not.supported/client", + "${app}/subscribe.reject.wildcard.subscriptions.not.supported/server"}) + public void shouldRejectWildcardSubscriptionsNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.reject.subscription.ids.not.supported/client", + "${app}/subscribe.reject.subscription.ids.not.supported/server"}) + public void shouldRejectSubscriptionIdentifiersNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.reject.shared.subscriptions.not.supported/client", + "${app}/subscribe.reject.shared.subscriptions.not.supported/server"}) + public void shouldRejectSharedSubscriptionsNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/subscribe.topic.filters.non.successful/client", + "${app}/subscribe.topic.filters.non.successful/server"}) + public void shouldFilterNonSuccessful() throws Exception + { + k3po.finish(); + } + + private static int subscriptionId = 0; + public static int supplySubscriptionId() + { + return ++subscriptionId; + } +} diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/UnsubscribeIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/UnsubscribeIT.java new file mode 100644 index 0000000000..f91ed01775 --- /dev/null +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/UnsubscribeIT.java @@ -0,0 +1,143 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.internal.stream.server; + +import static io.aklivity.zilla.runtime.binding.mqtt.internal.MqttConfiguration.PUBLISH_TIMEOUT; +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +import io.aklivity.zilla.runtime.engine.test.EngineRule; +import io.aklivity.zilla.runtime.engine.test.annotation.Configuration; + +public class UnsubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network") + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(10, SECONDS)); + + private final EngineRule engine = new EngineRule() + .directory("target/zilla-itests") + .countersBufferCapacity(8192) + .configure(PUBLISH_TIMEOUT, 1L) + .configure(ENGINE_DRAIN_ON_CLOSE, false) + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config") + .external("app0") + .clean(); + + @Rule + public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.after.subscribe/client", + "${app}/unsubscribe.after.subscribe/server"}) + public void shouldAcknowledge() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.topic.filter.single/client", + "${app}/unsubscribe.topic.filter.single/server"}) + public void shouldAcknowledgeSingleTopicFilters() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.publish.unfragmented/client", + "${app}/unsubscribe.publish.unfragmented/server"}) + public void shouldAcknowledgeAndPublishUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.aggregated.topic.filters.both.exact/client", + "${app}/unsubscribe.aggregated.topic.filters.both.exact/server"}) + public void shouldAcknowledgeAggregatedTopicFiltersBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.no.matching.subscription/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + public void shouldAcknowledgeNoMatchingSubscription() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.reject.invalid.fixed.header.flags/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + public void shouldRejectMalformedPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.reject.missing.packet.id/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + public void shouldRejectWithoutPacketId() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.reject.no.topic.filter/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + public void shouldRejectNoTopicFilter() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/unsubscribe.topic.filters.non.successful/client", + "${app}/unsubscribe.topic.filters.non.successful/server"}) + public void shouldAcknowledgeNonSuccessful() throws Exception + { + k3po.finish(); + } +} diff --git a/runtime/binding-proxy/pom.xml b/runtime/binding-proxy/pom.xml index 4572bcf950..1ae8b00a03 100644 --- a/runtime/binding-proxy/pom.xml +++ b/runtime/binding-proxy/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyAddressConfig.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyAddressConfig.java similarity index 93% rename from runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyAddressConfig.java rename to runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyAddressConfig.java index a872d1c8f6..59fcb38533 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyAddressConfig.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyAddressConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.proxy.internal.config; +package io.aklivity.zilla.runtime.binding.proxy.config; public class ProxyAddressConfig { diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfig.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyConditionConfig.java similarity index 95% rename from runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfig.java rename to runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyConditionConfig.java index e44b5b1efc..8bf709f4aa 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfig.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyConditionConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.proxy.internal.config; +package io.aklivity.zilla.runtime.binding.proxy.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyInfoConfig.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyInfoConfig.java similarity index 89% rename from runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyInfoConfig.java rename to runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyInfoConfig.java index a39d538989..e793b22577 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyInfoConfig.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyInfoConfig.java @@ -13,7 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.proxy.internal.config; +package io.aklivity.zilla.runtime.binding.proxy.config; + +import io.aklivity.zilla.runtime.binding.proxy.internal.config.ProxySecureInfoConfig; public class ProxyInfoConfig { diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfig.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyOptionsConfig.java similarity index 92% rename from runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfig.java rename to runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyOptionsConfig.java index 44b9e06477..7ad2317a50 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfig.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/config/ProxyOptionsConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.proxy.internal.config; +package io.aklivity.zilla.runtime.binding.proxy.config; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyAddressConfigAdapter.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyAddressConfigAdapter.java index e001175509..7f35dfa85e 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyAddressConfigAdapter.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyAddressConfigAdapter.java @@ -20,6 +20,8 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyAddressConfig; + public final class ProxyAddressConfigAdapter implements JsonbAdapter { private static final String HOST_NAME = "host"; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyBindingConfig.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyBindingConfig.java index 81797477ef..247e13fbb7 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyBindingConfig.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyBindingConfig.java @@ -19,6 +19,7 @@ import java.util.List; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyOptionsConfig; import io.aklivity.zilla.runtime.binding.proxy.internal.types.stream.ProxyBeginExFW; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapter.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapter.java index 4cd6486322..7e561d3df4 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapter.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapter.java @@ -20,6 +20,9 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyAddressConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyConditionConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyInfoConfig; import io.aklivity.zilla.runtime.binding.proxy.internal.ProxyBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionMatcher.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionMatcher.java index a6d3aaeb49..cc62d879e3 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionMatcher.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionMatcher.java @@ -46,6 +46,9 @@ import org.agrona.collections.MutableInteger; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyAddressConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyConditionConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyInfoConfig; import io.aklivity.zilla.runtime.binding.proxy.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.proxy.internal.types.OctetsFW; import io.aklivity.zilla.runtime.binding.proxy.internal.types.ProxyAddressFW; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyInfoConfigAdapter.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyInfoConfigAdapter.java index 54efa1b3c7..574b7ef129 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyInfoConfigAdapter.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyInfoConfigAdapter.java @@ -23,6 +23,8 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyInfoConfig; + public final class ProxyInfoConfigAdapter implements JsonbAdapter { private static final String ALPN_NAME = "alpn"; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapter.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapter.java index c854084c23..4268f92a72 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapter.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyOptionsConfig; import io.aklivity.zilla.runtime.binding.proxy.internal.ProxyBinding; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; diff --git a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyRouteConfig.java b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyRouteConfig.java index 26e51ea4f6..0c8a57f1be 100644 --- a/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyRouteConfig.java +++ b/runtime/binding-proxy/src/main/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyRouteConfig.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.function.LongPredicate; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyConditionConfig; import io.aklivity.zilla.runtime.binding.proxy.internal.types.stream.ProxyBeginExFW; import io.aklivity.zilla.runtime.engine.config.RouteConfig; diff --git a/runtime/binding-proxy/src/main/moditect/module-info.java b/runtime/binding-proxy/src/main/moditect/module-info.java index 2864f16717..dddbb108e0 100644 --- a/runtime/binding-proxy/src/main/moditect/module-info.java +++ b/runtime/binding-proxy/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.proxy.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.proxy.internal.ProxyBindingFactorySpi; diff --git a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapterTest.java b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapterTest.java index e4fa86d343..999d1a8ec3 100644 --- a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapterTest.java +++ b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyConditionConfigAdapterTest.java @@ -28,6 +28,10 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyAddressConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyConditionConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyInfoConfig; + public class ProxyConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyMatcherTest.java b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyMatcherTest.java index bcdd75130d..48757416a4 100644 --- a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyMatcherTest.java +++ b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyMatcherTest.java @@ -29,6 +29,9 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyAddressConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyConditionConfig; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyInfoConfig; import io.aklivity.zilla.runtime.binding.proxy.internal.types.stream.ProxyBeginExFW; public class ProxyMatcherTest diff --git a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapterTest.java b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapterTest.java index e17f917e07..8dc2e8a69e 100644 --- a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapterTest.java +++ b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/config/ProxyOptionsConfigAdapterTest.java @@ -27,6 +27,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.proxy.config.ProxyOptionsConfig; + public class ProxyOptionsConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyClientIT.java b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyClientIT.java index 31cb12223b..2212900dea 100644 --- a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyClientIT.java +++ b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyClientIT.java @@ -45,9 +45,7 @@ public class ProxyClientIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/proxy/config") .external("net0") .clean(); diff --git a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyServerIT.java b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyServerIT.java index 97694924fa..117a75ef65 100644 --- a/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyServerIT.java +++ b/runtime/binding-proxy/src/test/java/io/aklivity/zilla/runtime/binding/proxy/internal/streams/ProxyServerIT.java @@ -39,9 +39,7 @@ public class ProxyServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/proxy/config") .external("app0") .clean(); diff --git a/runtime/binding-sse-kafka/pom.xml b/runtime/binding-sse-kafka/pom.xml index 1d47caefea..379a403f1b 100644 --- a/runtime/binding-sse-kafka/pom.xml +++ b/runtime/binding-sse-kafka/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfig.java b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/config/SseKafkaConditionConfig.java similarity index 92% rename from runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfig.java rename to runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/config/SseKafkaConditionConfig.java index 548047cf50..8681ab6ab0 100644 --- a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfig.java +++ b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/config/SseKafkaConditionConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.binding.sse.kafka.internal.config; +package io.aklivity.zilla.runtime.binding.sse.kafka.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapter.java b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapter.java index e8ea4138c6..c1430063f8 100644 --- a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapter.java +++ b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapter.java @@ -19,6 +19,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.sse.kafka.config.SseKafkaConditionConfig; import io.aklivity.zilla.runtime.binding.sse.kafka.internal.SseKafkaBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; diff --git a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionMatcher.java b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionMatcher.java index 4a2cb2d462..a39f06093f 100644 --- a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionMatcher.java +++ b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionMatcher.java @@ -18,6 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.sse.kafka.config.SseKafkaConditionConfig; + public final class SseKafkaConditionMatcher { private final Matcher path; diff --git a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaRouteConfig.java b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaRouteConfig.java index 0d626883bc..abbee580bb 100644 --- a/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaRouteConfig.java +++ b/runtime/binding-sse-kafka/src/main/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaRouteConfig.java @@ -25,11 +25,11 @@ import java.util.regex.MatchResult; import java.util.stream.Collectors; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.sse.kafka.config.SseKafkaConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; import io.aklivity.zilla.runtime.engine.util.function.LongObjectBiFunction; -public final class SseKafkaRouteConfig extends OptionsConfig +public final class SseKafkaRouteConfig { public final long id; public final Optional with; diff --git a/runtime/binding-sse-kafka/src/main/moditect/module-info.java b/runtime/binding-sse-kafka/src/main/moditect/module-info.java index 0ae98e756f..abfc9307e6 100644 --- a/runtime/binding-sse-kafka/src/main/moditect/module-info.java +++ b/runtime/binding-sse-kafka/src/main/moditect/module-info.java @@ -16,6 +16,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.sse.kafka.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.sse.kafka.internal.SseKafkaBindingFactorySpi; diff --git a/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapterTest.java b/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapterTest.java index 17bb8a46df..98e7308c57 100644 --- a/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapterTest.java +++ b/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/config/SseKafkaConditionConfigAdapterTest.java @@ -26,6 +26,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.sse.kafka.config.SseKafkaConditionConfig; + public class SseKafkaConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/stream/SseKafkaProxyIT.java b/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/stream/SseKafkaProxyIT.java index 69b6b85b1b..6990dc85d2 100644 --- a/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/stream/SseKafkaProxyIT.java +++ b/runtime/binding-sse-kafka/src/test/java/io/aklivity/zilla/runtime/binding/sse/kafka/internal/stream/SseKafkaProxyIT.java @@ -39,9 +39,7 @@ public class SseKafkaProxyIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .configurationRoot("io/aklivity/zilla/specs/binding/sse/kafka/config") .external("kafka0") diff --git a/runtime/binding-sse/pom.xml b/runtime/binding-sse/pom.xml index 2e396c7f6a..0db4d56018 100644 --- a/runtime/binding-sse/pom.xml +++ b/runtime/binding-sse/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfig.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/config/SseConditionConfig.java similarity index 93% rename from runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfig.java rename to runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/config/SseConditionConfig.java index 4a6b0523d2..0d6a8750d1 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfig.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/config/SseConditionConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.sse.internal.config; +package io.aklivity.zilla.runtime.binding.sse.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfig.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/config/SseOptionsConfig.java similarity index 80% rename from runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfig.java rename to runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/config/SseOptionsConfig.java index 17943e4217..d8bd6baff8 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfig.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/config/SseOptionsConfig.java @@ -13,20 +13,13 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.sse.internal.config; +package io.aklivity.zilla.runtime.binding.sse.config; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; public final class SseOptionsConfig extends OptionsConfig { - static final int RETRY_DEFAULT = 2000; - - public int retry; - - public SseOptionsConfig() - { - this(RETRY_DEFAULT); - } + public final int retry; public SseOptionsConfig( int retry) diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseBindingConfig.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseBindingConfig.java index ae9e1cefa5..048347fd43 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseBindingConfig.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseBindingConfig.java @@ -15,16 +15,18 @@ */ package io.aklivity.zilla.runtime.binding.sse.internal.config; +import static io.aklivity.zilla.runtime.binding.sse.internal.config.SseOptionsConfigAdapter.RETRY_DEFAULT; import static java.util.stream.Collectors.toList; import java.util.List; +import io.aklivity.zilla.runtime.binding.sse.config.SseOptionsConfig; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; public final class SseBindingConfig { - private static final SseOptionsConfig DEFAULT_OPTIONS = new SseOptionsConfig(); + private static final SseOptionsConfig DEFAULT_OPTIONS = new SseOptionsConfig(RETRY_DEFAULT); public final long id; public final String name; diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapter.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapter.java index 4d9da66ff4..e57ddd58d5 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapter.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.sse.config.SseConditionConfig; import io.aklivity.zilla.runtime.binding.sse.internal.SseBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionMatcher.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionMatcher.java index 03bf8e9f4b..4824a1cf79 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionMatcher.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionMatcher.java @@ -18,6 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.sse.config.SseConditionConfig; + public final class SseConditionMatcher { private final Matcher path; diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapter.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapter.java index 40848ff165..733bb75f7c 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapter.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.sse.config.SseOptionsConfig; import io.aklivity.zilla.runtime.binding.sse.internal.SseBinding; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; @@ -27,6 +28,7 @@ public final class SseOptionsConfigAdapter implements OptionsConfigAdapterSpi, JsonbAdapter { private static final String RETRY_NAME = "retry"; + public static final int RETRY_DEFAULT = 2000; @Override public Kind kind() @@ -48,7 +50,7 @@ public JsonObject adaptToJson( JsonObjectBuilder object = Json.createObjectBuilder(); - if (sseOptions.retry != SseOptionsConfig.RETRY_DEFAULT) + if (sseOptions.retry != SseOptionsConfigAdapter.RETRY_DEFAULT) { object.add(RETRY_NAME, sseOptions.retry); } @@ -62,7 +64,7 @@ public OptionsConfig adaptFromJson( { int retry = object.containsKey(RETRY_NAME) ? object.getInt(RETRY_NAME) - : SseOptionsConfig.RETRY_DEFAULT; + : SseOptionsConfigAdapter.RETRY_DEFAULT; return new SseOptionsConfig(retry); } diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseRouteConfig.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseRouteConfig.java index b0c9ce3aea..2b5e0f25a8 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseRouteConfig.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseRouteConfig.java @@ -20,10 +20,10 @@ import java.util.List; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.sse.config.SseConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class SseRouteConfig extends OptionsConfig +public final class SseRouteConfig { public final long id; diff --git a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/stream/SseServerFactory.java b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/stream/SseServerFactory.java index 46bcbf0558..ae4827c9ee 100644 --- a/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/stream/SseServerFactory.java +++ b/runtime/binding-sse/src/main/java/io/aklivity/zilla/runtime/binding/sse/internal/stream/SseServerFactory.java @@ -347,8 +347,8 @@ private final class SseServer private long httpReplyBud; private int httpReplyPad; private long httpReplyAuth; - private BudgetDebitor replyDebitor; - private long replyDebitorIndex = NO_DEBITOR_INDEX; + private BudgetDebitor replyDeb; + private long replyDebIndex = NO_DEBITOR_INDEX; private SseServer( MessageConsumer network, @@ -518,13 +518,13 @@ private void onNetWindow( assert httpReplyAck <= httpReplySeq; - if (httpReplyBud != 0L && replyDebitorIndex == NO_DEBITOR_INDEX) + if (httpReplyBud != 0L && replyDebIndex == NO_DEBITOR_INDEX) { - replyDebitor = supplyDebitor.apply(budgetId); - replyDebitorIndex = replyDebitor.acquire(budgetId, replyId, this::flushNetwork); + replyDeb = supplyDebitor.apply(budgetId); + replyDebIndex = replyDeb.acquire(budgetId, replyId, this::flushNetwork); } - if (httpReplyBud != 0L && replyDebitorIndex == NO_DEBITOR_INDEX) + if (httpReplyBud != 0L && replyDebIndex == NO_DEBITOR_INDEX) { doNetAbort(traceId, authorization); stream.doAppEndDeferred(traceId, authorization); @@ -617,7 +617,7 @@ else if (name.equals(HEADER_NAME_METHOD)) buffer.putBytes(networkSlotOffset, data.buffer(), data.offset(), data.sizeof()); networkSlotOffset += data.sizeof(); - if (replyDebitorIndex != NO_DEBITOR_INDEX) + if (replyDebIndex != NO_DEBITOR_INDEX) { deferredClaim += data.reserved(); } @@ -784,9 +784,9 @@ private void encodeNetwork( } int claimed = reserved; - if (replyDebitorIndex != NO_DEBITOR_INDEX) + if (replyDebIndex != NO_DEBITOR_INDEX) { - claimed = replyDebitor.claim(traceId, replyDebitorIndex, replyId, + claimed = replyDeb.claim(traceId, replyDebIndex, replyId, reserved, reserved, 0); } @@ -805,9 +805,9 @@ private void encodeNetwork( if (deferredClaim > 0) { - assert replyDebitorIndex != NO_DEBITOR_INDEX; + assert replyDebIndex != NO_DEBITOR_INDEX; - int claimed = replyDebitor.claim(traceId, replyDebitorIndex, replyId, + int claimed = replyDeb.claim(traceId, replyDebIndex, replyId, deferredClaim, deferredClaim, 0); if (claimed == deferredClaim) @@ -851,11 +851,11 @@ private void encodeNetwork( private void cleanupDebitorIfNecessary() { - if (replyDebitorIndex != NO_DEBITOR_INDEX) + if (replyDebIndex != NO_DEBITOR_INDEX) { - replyDebitor.release(replyDebitorIndex, replyId); - replyDebitor = null; - replyDebitorIndex = NO_DEBITOR_INDEX; + replyDeb.release(replyDebIndex, replyId); + replyDeb = null; + replyDebIndex = NO_DEBITOR_INDEX; } } @@ -1100,7 +1100,7 @@ private void onAppEnd( buffer.putBytes(networkSlotOffset, data.buffer(), data.offset(), data.sizeof()); networkSlotOffset += data.sizeof(); - if (replyDebitorIndex != NO_DEBITOR_INDEX) + if (replyDebIndex != NO_DEBITOR_INDEX) { deferredClaim += data.reserved(); } diff --git a/runtime/binding-sse/src/main/moditect/module-info.java b/runtime/binding-sse/src/main/moditect/module-info.java index 52b40d4046..813f34dfde 100644 --- a/runtime/binding-sse/src/main/moditect/module-info.java +++ b/runtime/binding-sse/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.sse.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.sse.internal.SseBindingFactorySpi; diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapterTest.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapterTest.java index 8f0596ec77..8fe4d14ea4 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapterTest.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseConditionConfigAdapterTest.java @@ -27,6 +27,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.sse.config.SseConditionConfig; + public class SseConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapterTest.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapterTest.java index 3871942aa4..77c1e353a9 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapterTest.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/config/SseOptionsConfigAdapterTest.java @@ -27,6 +27,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.sse.config.SseOptionsConfig; + public class SseOptionsConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/AdvisoryIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/AdvisoryIT.java index da8286f10b..8f0231c9c0 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/AdvisoryIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/AdvisoryIT.java @@ -39,9 +39,7 @@ public class AdvisoryIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(2048) - .responseBufferCapacity(2048) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("net0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ByteOrderMarkIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ByteOrderMarkIT.java index bc7fb22d52..f3480a8c5e 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ByteOrderMarkIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ByteOrderMarkIT.java @@ -39,9 +39,7 @@ public class ByteOrderMarkIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("net0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/DataIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/DataIT.java index 509bb22539..c42a761436 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/DataIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/DataIT.java @@ -40,9 +40,7 @@ public class DataIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) .external("net0") diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/EndOfLineIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/EndOfLineIT.java index 2ae9c51ab2..deed2563a5 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/EndOfLineIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/EndOfLineIT.java @@ -39,9 +39,7 @@ public class EndOfLineIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("net0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ErrorIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ErrorIT.java index 0d5dcd5220..a091196951 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ErrorIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ErrorIT.java @@ -39,9 +39,7 @@ public class ErrorIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(2048) - .responseBufferCapacity(2048) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("net0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/HandshakeIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/HandshakeIT.java index 88c71cf12f..6e33f4fdf9 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/HandshakeIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/HandshakeIT.java @@ -39,9 +39,7 @@ public class HandshakeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("net0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ReconnectIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ReconnectIT.java index 2b5ce15a6d..377ba88b33 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ReconnectIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/ReconnectIT.java @@ -39,9 +39,7 @@ public class ReconnectIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("net0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/TypeIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/TypeIT.java index b92285e405..f115e327fd 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/TypeIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/client/TypeIT.java @@ -41,9 +41,7 @@ public class TypeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("net0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/AdvisoryIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/AdvisoryIT.java index bc5a5113dd..19aa21e0af 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/AdvisoryIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/AdvisoryIT.java @@ -39,9 +39,7 @@ public class AdvisoryIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(2048) - .responseBufferCapacity(2048) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ChallengeIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ChallengeIT.java index 36684efa57..a5f7800331 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ChallengeIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ChallengeIT.java @@ -39,9 +39,7 @@ public class ChallengeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(2048) - .responseBufferCapacity(2048) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/DataIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/DataIT.java index 1227e5a6f2..8033f9be7b 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/DataIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/DataIT.java @@ -40,9 +40,7 @@ public class DataIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ErrorIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ErrorIT.java index b745a1030a..d0ec0e9cf3 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ErrorIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ErrorIT.java @@ -39,9 +39,7 @@ public class ErrorIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(2048) - .responseBufferCapacity(2048) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/HandshakeIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/HandshakeIT.java index f59f21491b..e15d239c4b 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/HandshakeIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/HandshakeIT.java @@ -41,9 +41,7 @@ public class HandshakeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/IdIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/IdIT.java index 8c483c61f8..72111649d7 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/IdIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/IdIT.java @@ -38,10 +38,7 @@ public class IdIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ReconnectIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ReconnectIT.java index 11fe77db3a..11ca12284e 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ReconnectIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/ReconnectIT.java @@ -39,9 +39,7 @@ public class ReconnectIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TimestampIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TimestampIT.java index 205e6dd0a4..a77dd58a57 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TimestampIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TimestampIT.java @@ -40,9 +40,7 @@ public class TimestampIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TypeIT.java b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TypeIT.java index 70088fe4d4..6742fb2209 100644 --- a/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TypeIT.java +++ b/runtime/binding-sse/src/test/java/io/aklivity/zilla/runtime/binding/sse/internal/streams/server/TypeIT.java @@ -41,9 +41,7 @@ public class TypeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/sse/config") .external("app0") .clean(); diff --git a/runtime/binding-tcp/NOTICE b/runtime/binding-tcp/NOTICE index 6deac3d29c..08323b88fb 100644 --- a/runtime/binding-tcp/NOTICE +++ b/runtime/binding-tcp/NOTICE @@ -12,12 +12,6 @@ specific language governing permissions and limitations under the License. This project includes: - agrona under The Apache License, Version 2.0 - ICU4J under Unicode/ICU License - Jakarta JSON Processing API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception - JSON-B API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception - org.leadpony.justify under The Apache Software License, Version 2.0 - zilla::runtime::engine under The Apache Software License, Version 2.0 This project also includes code under copyright of the following entities: diff --git a/runtime/binding-tcp/pom.xml b/runtime/binding-tcp/pom.xml index 747b4b3a21..8f8c51f266 100644 --- a/runtime/binding-tcp/pom.xml +++ b/runtime/binding-tcp/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml @@ -41,6 +41,7 @@ ${project.groupId} engine ${project.version} + true
${project.groupId} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpConditionConfig.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpConditionConfig.java new file mode 100644 index 0000000000..6e9b53d85f --- /dev/null +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpConditionConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tcp.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; + +public final class TcpConditionConfig extends ConditionConfig +{ + public final String cidr; + public final String authority; + public final int[] ports; + + public static TcpConditionConfigBuilder builder() + { + return new TcpConditionConfigBuilder<>(TcpConditionConfig.class::cast); + } + + public static TcpConditionConfigBuilder builder( + Function mapper) + { + return new TcpConditionConfigBuilder<>(mapper); + } + + TcpConditionConfig( + String cidr, + String authority, + int[] ports) + { + this.cidr = cidr; + this.authority = authority; + this.ports = ports; + } +} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpConditionConfigBuilder.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpConditionConfigBuilder.java new file mode 100644 index 0000000000..a597932f67 --- /dev/null +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpConditionConfigBuilder.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tcp.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class TcpConditionConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String cidr; + private String authority; + private int[] ports; + + TcpConditionConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TcpConditionConfigBuilder cidr( + String cidr) + { + this.cidr = cidr; + return this; + } + + public TcpConditionConfigBuilder authority( + String authority) + { + this.authority = authority; + return this; + } + + public TcpConditionConfigBuilder ports( + int[] ports) + { + this.ports = ports; + return this; + } + + @Override + public T build() + { + return mapper.apply(new TcpConditionConfig(cidr, authority, ports)); + } +} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpOptionsConfig.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpOptionsConfig.java new file mode 100644 index 0000000000..20427f1024 --- /dev/null +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpOptionsConfig.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tcp.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TcpOptionsConfig extends OptionsConfig +{ + public final String host; + public final int[] ports; + public final int backlog; + public final boolean nodelay; + public final boolean keepalive; + + public static TcpOptionsConfigBuilder builder() + { + return new TcpOptionsConfigBuilder<>(TcpOptionsConfig.class::cast); + } + + public static TcpOptionsConfigBuilder builder( + Function mapper) + { + return new TcpOptionsConfigBuilder<>(mapper); + } + + TcpOptionsConfig( + String host, + int[] ports, + int backlog, + boolean nodelay, + boolean keepalive) + { + this.host = host; + this.ports = ports; + this.backlog = backlog; + this.nodelay = nodelay; + this.keepalive = keepalive; + } +} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpOptionsConfigBuilder.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpOptionsConfigBuilder.java new file mode 100644 index 0000000000..7a858222e0 --- /dev/null +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/config/TcpOptionsConfigBuilder.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tcp.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TcpOptionsConfigBuilder extends ConfigBuilder> +{ + public static final int BACKLOG_DEFAULT = 0; + public static final boolean NODELAY_DEFAULT = true; + public static final boolean KEEPALIVE_DEFAULT = false; + + private final Function mapper; + + private String host; + private int[] ports; + private int backlog = BACKLOG_DEFAULT; + private boolean nodelay = NODELAY_DEFAULT; + private boolean keepalive = KEEPALIVE_DEFAULT; + + TcpOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TcpOptionsConfigBuilder host( + String host) + { + this.host = host; + return this; + } + + public TcpOptionsConfigBuilder ports( + int[] ports) + { + this.ports = ports; + return this; + } + + public TcpOptionsConfigBuilder backlog( + int backlog) + { + this.backlog = backlog; + return this; + } + + public TcpOptionsConfigBuilder nodelay( + boolean nodelay) + { + this.nodelay = nodelay; + return this; + } + + public TcpOptionsConfigBuilder keepalive( + boolean keepalive) + { + this.keepalive = keepalive; + return this; + } + + @Override + public T build() + { + return mapper.apply(new TcpOptionsConfig(host, ports, backlog, nodelay, keepalive)); + } +} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpBindingConfig.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpBindingConfig.java index 3b848aba6c..3f6e5e0276 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpBindingConfig.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpBindingConfig.java @@ -21,6 +21,7 @@ import java.net.InetSocketAddress; import java.util.List; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; @@ -69,7 +70,7 @@ public TcpRouteConfig resolve( private static List initDefaultClientRoutes() { - final RouteConfig route = new RouteConfig(null); + final RouteConfig route = RouteConfig.builder().build(); route.authorized = id -> true; return singletonList(new TcpRouteConfig(route)); diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfig.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfig.java deleted file mode 100644 index 5c205199e4..0000000000 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.tcp.internal.config; - -import io.aklivity.zilla.runtime.engine.config.ConditionConfig; - -public final class TcpConditionConfig extends ConditionConfig -{ - public final String cidr; - public final String authority; - public final int[] ports; - - public TcpConditionConfig( - String cidr, - String authority, - int[] ports) - { - this.cidr = cidr; - this.authority = authority; - this.ports = ports; - } -} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapter.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapter.java index 21778d265c..3c5da83525 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapter.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapter.java @@ -28,6 +28,8 @@ import org.agrona.collections.IntHashSet; import org.agrona.collections.MutableInteger; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfig; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfigBuilder; import io.aklivity.zilla.runtime.binding.tcp.internal.TcpBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; @@ -87,14 +89,22 @@ public JsonObject adaptToJson( public ConditionConfig adaptFromJson( JsonObject object) { - String cidr = object.containsKey(CIDR_NAME) ? object.getString(CIDR_NAME) : null; - String authority = object.containsKey(AUTHORITY_NAME) ? object.getString(AUTHORITY_NAME) : null; - JsonValue portsValue = object.containsKey(PORT_NAME) ? object.get(PORT_NAME) : null; + TcpConditionConfigBuilder tcpCondition = TcpConditionConfig.builder(); - int[] ports = null; + if (object.containsKey(CIDR_NAME)) + { + tcpCondition.cidr(object.getString(CIDR_NAME)); + } - if (portsValue != null) + if (object.containsKey(AUTHORITY_NAME)) { + tcpCondition.authority(object.getString(AUTHORITY_NAME)); + } + + if (object.containsKey(PORT_NAME)) + { + JsonValue portsValue = object.get(PORT_NAME); + IntHashSet portsSet = new IntHashSet(); switch (portsValue.getValueType()) { @@ -107,12 +117,13 @@ public ConditionConfig adaptFromJson( break; } - int[] ports0 = new int[portsSet.size()]; + int[] ports = new int[portsSet.size()]; MutableInteger index = new MutableInteger(); - portsSet.forEach(i -> ports0[index.value++] = i); - ports = ports0; + portsSet.forEach(i -> ports[index.value++] = i); + + tcpCondition.ports(ports); } - return new TcpConditionConfig(cidr, authority, ports); + return tcpCondition.build(); } } diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionMatcher.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionMatcher.java index b1e23fb52a..f286b41635 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionMatcher.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionMatcher.java @@ -23,6 +23,7 @@ import org.agrona.collections.IntHashSet; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.util.Cidr; public final class TcpConditionMatcher diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfig.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfig.java deleted file mode 100644 index 78ff5214e3..0000000000 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.tcp.internal.config; - -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public final class TcpOptionsConfig extends OptionsConfig -{ - public final String host; - public final int[] ports; - public final int backlog; - public final boolean nodelay; - public final boolean keepalive; - - public TcpOptionsConfig( - String host, - int[] ports, - int backlog, - boolean nodelay, - boolean keepalive) - { - this.host = host; - this.ports = ports; - this.backlog = backlog; - this.nodelay = nodelay; - this.keepalive = keepalive; - } -} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapter.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapter.java index 128e004d5a..ed8fa00d99 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapter.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapter.java @@ -15,6 +15,10 @@ */ package io.aklivity.zilla.runtime.binding.tcp.internal.config; +import static io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfigBuilder.BACKLOG_DEFAULT; +import static io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfigBuilder.KEEPALIVE_DEFAULT; +import static io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfigBuilder.NODELAY_DEFAULT; + import java.util.stream.IntStream; import jakarta.json.Json; @@ -30,6 +34,8 @@ import org.agrona.collections.IntHashSet; import org.agrona.collections.MutableInteger; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfigBuilder; import io.aklivity.zilla.runtime.binding.tcp.internal.TcpBinding; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; @@ -40,10 +46,6 @@ public final class TcpOptionsConfigAdapter implements OptionsConfigAdapterSpi, J private static final String PORT_NAME = "port"; private static final String BACKLOG_NAME = "backlog"; - private static final int BACKLOG_DEFAULT = 0; - private static final boolean NODELAY_DEFAULT = true; - private static final boolean KEEPALIVE_DEFAULT = false; - @Override public Kind kind() { @@ -99,14 +101,12 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - String host = object.getString(HOST_NAME); - JsonValue portsValue = object.get(PORT_NAME); - int backlog = object.containsKey(BACKLOG_NAME) ? object.getJsonNumber(BACKLOG_NAME).intValue() : BACKLOG_DEFAULT; - boolean nodelay = NODELAY_DEFAULT; - boolean keepalive = KEEPALIVE_DEFAULT; + final TcpOptionsConfigBuilder tcpOptions = TcpOptionsConfig.builder(); - IntHashSet portsSet = new IntHashSet(); + tcpOptions.host(object.getString(HOST_NAME)); + JsonValue portsValue = object.get(PORT_NAME); + IntHashSet portsSet = new IntHashSet(); switch (portsValue.getValueType()) { case ARRAY: @@ -121,8 +121,14 @@ public OptionsConfig adaptFromJson( int[] ports = new int[portsSet.size()]; MutableInteger index = new MutableInteger(); portsSet.forEach(i -> ports[index.value++] = i); + tcpOptions.ports(ports); + + if (object.containsKey(BACKLOG_NAME)) + { + tcpOptions.backlog(object.getJsonNumber(BACKLOG_NAME).intValue()); + } - return new TcpOptionsConfig(host, ports, backlog, nodelay, keepalive); + return tcpOptions.build(); } static void adaptPortsValueFromJson( diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpRouteConfig.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpRouteConfig.java index ecb17f4b97..2a97bea824 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpRouteConfig.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpRouteConfig.java @@ -22,6 +22,7 @@ import java.util.function.LongPredicate; import java.util.function.Predicate; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; public final class TcpRouteConfig diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpServerBindingConfig.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpServerBindingConfig.java index 104520b41e..5cb033a872 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpServerBindingConfig.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpServerBindingConfig.java @@ -29,6 +29,8 @@ import org.agrona.LangUtil; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; + public final class TcpServerBindingConfig { public final long id; diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java index 52841d2f4f..d75b87d5e7 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java @@ -42,9 +42,9 @@ import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.TcpConfiguration; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpBindingConfig; -import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpOptionsConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.tcp.internal.types.OctetsFW; import io.aklivity.zilla.runtime.binding.tcp.internal.types.stream.AbortFW; @@ -330,8 +330,14 @@ private int onNetReadable( ((Buffer) readByteBuffer).position(0); ((Buffer) readByteBuffer).limit(limit); + read: try { + if (!TcpState.opened(state)) + { + break read; + } + final int bytesRead = net.read(readByteBuffer); if (bytesRead == -1) diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java index 70f0c5013e..9f67193d7c 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java @@ -29,8 +29,8 @@ import org.agrona.collections.Long2ObjectHashMap; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpBindingConfig; -import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpOptionsConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpRouteConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.tcp.internal.types.OctetsFW; diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java index 06d151981a..384e79d496 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java @@ -43,9 +43,9 @@ import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.TcpConfiguration; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpBindingConfig; -import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpOptionsConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpRouteConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpServerBindingConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.types.Flyweight; diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpState.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpState.java index 239f656862..cf52ffe211 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpState.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpState.java @@ -122,6 +122,12 @@ static boolean replyClosed( return (state & REPLY_CLOSED) != 0; } + static boolean opened( + int state) + { + return initialOpened(state) && replyOpened(state); + } + private TcpState() { // utility diff --git a/runtime/binding-tcp/src/main/moditect/module-info.java b/runtime/binding-tcp/src/main/moditect/module-info.java index 12014cc672..103492b28c 100644 --- a/runtime/binding-tcp/src/main/moditect/module-info.java +++ b/runtime/binding-tcp/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.tcp.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.tcp.internal.TcpBindingFactorySpi; diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapterTest.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapterTest.java index 5ae0a6dc86..8a095f9371 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapterTest.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpConditionConfigAdapterTest.java @@ -15,6 +15,7 @@ */ package io.aklivity.zilla.runtime.binding.tcp.internal.config; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -27,6 +28,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpConditionConfig; + public class TcpConditionConfigAdapterTest { private Jsonb jsonb; @@ -62,13 +65,19 @@ public void shouldReadCondition() @Test public void shouldWriteCondition() { - TcpConditionConfig condition = new TcpConditionConfig("127.0.0.0/24", "*.example.net", new int[] { 8080 }); + TcpConditionConfig condition = TcpConditionConfig.builder() + .inject(identity()) + .cidr("127.0.0.0/24") + .authority("*.example.net") + .ports(new int[] { 8080 }) + .build(); String text = jsonb.toJson(condition); assertThat(text, not(nullValue())); assertThat(text, equalTo("{\"cidr\":\"127.0.0.0/24\",\"authority\":\"*.example.net\",\"port\":8080}")); } + @Test public void shouldReadConditionWithPortRange() { diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapterTest.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapterTest.java index c2038ceaf0..7a0e9db8cf 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapterTest.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/config/TcpOptionsConfigAdapterTest.java @@ -15,6 +15,7 @@ */ package io.aklivity.zilla.runtime.binding.tcp.internal.config; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -27,6 +28,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; + public class TcpOptionsConfigAdapterTest { private Jsonb jsonb; @@ -97,7 +100,11 @@ public void shouldReadOptionsWithPortRangeSingleton() @Test public void shouldWriteOptions() { - TcpOptionsConfig options = new TcpOptionsConfig("localhost", new int[] { 8080 }, 0, true, false); + TcpOptionsConfig options = TcpOptionsConfig.builder() + .inject(identity()) + .host("localhost") + .ports(new int[] { 8080 }) + .build(); String text = jsonb.toJson(options); @@ -128,7 +135,12 @@ public void shouldReadOptionsWithBacklog() @Test public void shouldWriteOptionsWithBacklog() { - TcpOptionsConfig options = new TcpOptionsConfig("localhost", new int[] { 8080 }, 1000, true, false); + TcpOptionsConfig options = TcpOptionsConfig.builder() + .inject(identity()) + .host("localhost") + .ports(new int[] { 8080 }) + .backlog(1000) + .build(); String text = jsonb.toJson(options); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromReadIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromReadIT.java index bccb9ddb36..59073e4b8c 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromReadIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromReadIT.java @@ -44,9 +44,7 @@ public class ClientIOExceptionFromReadIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromWriteIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromWriteIT.java index 762fd7ad18..6d7e53a22b 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromWriteIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIOExceptionFromWriteIT.java @@ -50,9 +50,7 @@ public class ClientIOExceptionFromWriteIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIT.java index 5a3b4ff4a2..cd69d87413 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientIT.java @@ -48,9 +48,7 @@ public class ClientIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientLimitsIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientLimitsIT.java index a9063eabde..da7a350a5b 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientLimitsIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientLimitsIT.java @@ -46,9 +46,7 @@ public class ClientLimitsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 16) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteIT.java index b21ae130a5..7ca8935eb4 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteIT.java @@ -64,9 +64,7 @@ public class ClientPartialWriteIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .external("app0") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteLimitsIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteLimitsIT.java index 935ed825c4..021a27a73a 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteLimitsIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientPartialWriteLimitsIT.java @@ -64,9 +64,7 @@ public class ClientPartialWriteLimitsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 16) .configure(ENGINE_BUFFER_POOL_CAPACITY, 16) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientResetAndAbortIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientResetAndAbortIT.java index 9a7cefd5be..7a971cd62c 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientResetAndAbortIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientResetAndAbortIT.java @@ -51,9 +51,7 @@ public class ClientResetAndAbortIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientRoutingIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientRoutingIT.java index e379328b4a..a2aad7fa70 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientRoutingIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ClientRoutingIT.java @@ -40,9 +40,7 @@ public class ClientRoutingIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromReadIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromReadIT.java index c38776f7ba..2906d2505e 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromReadIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromReadIT.java @@ -43,9 +43,7 @@ public class ServerIOExceptionFromReadIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .external("app0") diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromWriteIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromWriteIT.java index 1c7cd1e2f9..87e9c706d9 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromWriteIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIOExceptionFromWriteIT.java @@ -48,9 +48,7 @@ public class ServerIOExceptionFromWriteIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .external("app0") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIT.java index 3bef4e02ae..e28612865c 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerIT.java @@ -52,9 +52,7 @@ public class ServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(TCP_MAX_CONNECTIONS, 3) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerLimitsIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerLimitsIT.java index fd08831697..3a9c40cc29 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerLimitsIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerLimitsIT.java @@ -45,10 +45,7 @@ public class ServerLimitsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - // Initial window size for output to network: + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 16) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .external("app0") diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteIT.java index ef972e2fe6..f7979d5fdf 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteIT.java @@ -62,9 +62,7 @@ public class ServerPartialWriteIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .external("app0") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteLimitsIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteLimitsIT.java index 70e58b4ccb..f001f4c2d3 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteLimitsIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerPartialWriteLimitsIT.java @@ -62,12 +62,8 @@ public class ServerPartialWriteLimitsIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) - // Initial window size for output to network: + .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 16) - // Overall buffer pool size same as slot size so maximum concurrent streams with partial writes = 1 .configure(ENGINE_BUFFER_POOL_CAPACITY, 16) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .external("app0") diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerResetAndAbortIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerResetAndAbortIT.java index 73faa7f2e6..be07c9ef63 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerResetAndAbortIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerResetAndAbortIT.java @@ -50,9 +50,7 @@ public class ServerResetAndAbortIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") .external("app0") .clean(); diff --git a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerRoutingIT.java b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerRoutingIT.java index 7819bd8210..27b80370fc 100644 --- a/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerRoutingIT.java +++ b/runtime/binding-tcp/src/test/java/io/aklivity/zilla/runtime/binding/tcp/internal/streams/ServerRoutingIT.java @@ -41,9 +41,7 @@ public class ServerRoutingIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(TCP_MAX_CONNECTIONS, 3) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/specs/binding/tcp/config") diff --git a/runtime/binding-tls/pom.xml b/runtime/binding-tls/pom.xml index 06710910e4..decdebf311 100644 --- a/runtime/binding-tls/pom.xml +++ b/runtime/binding-tls/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsConditionConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsConditionConfig.java new file mode 100644 index 0000000000..473a7f90f2 --- /dev/null +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsConditionConfig.java @@ -0,0 +1,45 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tls.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; + +public final class TlsConditionConfig extends ConditionConfig +{ + public final String authority; + public final String alpn; + + public static TlsConditionConfigBuilder builder() + { + return new TlsConditionConfigBuilder<>(TlsConditionConfig.class::cast); + } + + public static TlsConditionConfigBuilder builder( + Function mapper) + { + return new TlsConditionConfigBuilder<>(mapper); + } + + TlsConditionConfig( + String authority, + String alpn) + { + this.authority = authority; + this.alpn = alpn; + } +} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsConditionConfigBuilder.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsConditionConfigBuilder.java new file mode 100644 index 0000000000..e1f6aa52f5 --- /dev/null +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsConditionConfigBuilder.java @@ -0,0 +1,62 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tls.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConditionConfig; +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class TlsConditionConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String authority; + private String alpn; + + TlsConditionConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TlsConditionConfigBuilder authority( + String authority) + { + this.authority = authority; + return this; + } + + public TlsConditionConfigBuilder alpn( + String alpn) + { + this.alpn = alpn; + return this; + } + + @Override + public T build() + { + return mapper.apply(new TlsConditionConfig(authority, alpn)); + } +} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsMutualConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsMutualConfig.java new file mode 100644 index 0000000000..03d153d3ff --- /dev/null +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsMutualConfig.java @@ -0,0 +1,23 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tls.config; + +public enum TlsMutualConfig +{ + NONE, + REQUESTED, + REQUIRED +} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsOptionsConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsOptionsConfig.java new file mode 100644 index 0000000000..c89313fe66 --- /dev/null +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsOptionsConfig.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tls.config; + +import java.util.List; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TlsOptionsConfig extends OptionsConfig +{ + public final String version; + public final List keys; + public final List trust; + public final List sni; + public final List alpn; + public final TlsMutualConfig mutual; + public final List signers; + public final boolean trustcacerts; + + public static TlsOptionsConfigBuilder builder() + { + return new TlsOptionsConfigBuilder<>(TlsOptionsConfig.class::cast); + } + + public static TlsOptionsConfigBuilder builder( + Function mapper) + { + return new TlsOptionsConfigBuilder<>(mapper); + } + + TlsOptionsConfig( + String version, + List keys, + List trust, + List sni, + List alpn, + TlsMutualConfig mutual, + List signers, + boolean trustcacerts) + { + this.version = version; + this.keys = keys; + this.trust = trust; + this.sni = sni; + this.alpn = alpn; + this.mutual = mutual; + this.signers = signers; + this.trustcacerts = trustcacerts; + } +} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsOptionsConfigBuilder.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsOptionsConfigBuilder.java new file mode 100644 index 0000000000..aaba789b99 --- /dev/null +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/config/TlsOptionsConfigBuilder.java @@ -0,0 +1,114 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.binding.tls.config; + +import static io.aklivity.zilla.runtime.binding.tls.config.TlsMutualConfig.REQUIRED; + +import java.util.List; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TlsOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String version; + private List keys; + private List trust; + private List sni; + private List alpn; + private TlsMutualConfig mutual; + private List signers; + private boolean trustcacerts; + + TlsOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TlsOptionsConfigBuilder version( + String version) + { + this.version = version; + return this; + } + + public TlsOptionsConfigBuilder keys( + List keys) + { + this.keys = keys; + return this; + } + + public TlsOptionsConfigBuilder trust( + List trust) + { + this.trust = trust; + return this; + } + + public TlsOptionsConfigBuilder sni( + List sni) + { + this.sni = sni; + return this; + } + + public TlsOptionsConfigBuilder alpn( + List alpn) + { + this.alpn = alpn; + return this; + } + + public TlsOptionsConfigBuilder mutual( + TlsMutualConfig mutual) + { + this.mutual = mutual; + return this; + } + + public TlsOptionsConfigBuilder signers( + List signers) + { + this.signers = signers; + return this; + } + + public TlsOptionsConfigBuilder trustcacerts( + boolean trustcacerts) + { + this.trustcacerts = trustcacerts; + return this; + } + + @Override + public T build() + { + TlsMutualConfig mutual = this.mutual == null && this.trust != null ? REQUIRED : this.mutual; + return mapper.apply(new TlsOptionsConfig(version, keys, trust, sni, alpn, mutual, signers, trustcacerts)); + } +} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java index f31e3fdef0..6fb1b5a0aa 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java @@ -49,6 +49,8 @@ import org.agrona.LangUtil; +import io.aklivity.zilla.runtime.binding.tls.config.TlsMutualConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfig; import io.aklivity.zilla.runtime.binding.tls.internal.TlsConfiguration; import io.aklivity.zilla.runtime.binding.tls.internal.identity.TlsClientX509ExtendedKeyManager; import io.aklivity.zilla.runtime.binding.tls.internal.types.Array32FW; @@ -242,7 +244,7 @@ public SSLEngine newServerEngine( engine = context.createSSLEngine(); engine.setUseClientMode(false); - TlsMutual mutual = Optional.ofNullable(options != null ? options.mutual : null).orElse(TlsMutual.NONE); + TlsMutualConfig mutual = Optional.ofNullable(options != null ? options.mutual : null).orElse(TlsMutualConfig.NONE); switch (mutual) { diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfig.java deleted file mode 100644 index ef4e33a446..0000000000 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.tls.internal.config; - -import io.aklivity.zilla.runtime.engine.config.ConditionConfig; - -public final class TlsConditionConfig extends ConditionConfig -{ - public final String authority; - public final String alpn; - - public TlsConditionConfig( - String authority, - String alpn) - { - this.authority = authority; - this.alpn = alpn; - } -} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapter.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapter.java index 45632931c6..0a6171a29a 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapter.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapter.java @@ -20,6 +20,8 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.tls.config.TlsConditionConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsConditionConfigBuilder; import io.aklivity.zilla.runtime.binding.tls.internal.TlsBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; @@ -60,13 +62,18 @@ public JsonObject adaptToJson( public ConditionConfig adaptFromJson( JsonObject object) { - String authority = object.containsKey(AUTHORITY_NAME) - ? object.getString(AUTHORITY_NAME) - : null; - String alpn = object.containsKey(ALPN_NAME) - ? object.getString(ALPN_NAME) - : null; + TlsConditionConfigBuilder tlsCondition = TlsConditionConfig.builder(); - return new TlsConditionConfig(authority, alpn); + if (object.containsKey(AUTHORITY_NAME)) + { + tlsCondition.authority(object.getString(AUTHORITY_NAME)); + } + + if (object.containsKey(ALPN_NAME)) + { + tlsCondition.alpn(object.getString(ALPN_NAME)); + } + + return tlsCondition.build(); } } diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionMatcher.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionMatcher.java index 2cd8bcb745..ba17acb12c 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionMatcher.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionMatcher.java @@ -18,6 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.tls.config.TlsConditionConfig; + public final class TlsConditionMatcher { public final Matcher authorityMatch; diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsMutual.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsMutual.java deleted file mode 100644 index 63443d3612..0000000000 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsMutual.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.tls.internal.config; - -public enum TlsMutual -{ - NONE, - REQUESTED, - REQUIRED -} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfig.java deleted file mode 100644 index 3d9f520a6e..0000000000 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfig.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.binding.tls.internal.config; - -import java.util.List; - -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public final class TlsOptionsConfig extends OptionsConfig -{ - public final String version; - public final List keys; - public final List trust; - public final List sni; - public final List alpn; - public final TlsMutual mutual; - public final List signers; - public final boolean trustcacerts; - - public TlsOptionsConfig( - String version, - List keys, - List trust, - List sni, - List alpn, - TlsMutual mutual, - List signers, - boolean trustcacerts) - { - this.version = version; - this.keys = keys; - this.trust = trust; - this.sni = sni; - this.alpn = alpn; - this.mutual = mutual; - this.signers = signers; - this.trustcacerts = trustcacerts; - } -} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapter.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapter.java index 54d968dfc0..d61e50819d 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapter.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapter.java @@ -15,7 +15,7 @@ */ package io.aklivity.zilla.runtime.binding.tls.internal.config; -import static io.aklivity.zilla.runtime.binding.tls.internal.config.TlsMutual.REQUIRED; +import static io.aklivity.zilla.runtime.binding.tls.config.TlsMutualConfig.REQUIRED; import static java.util.stream.Collectors.toList; import java.util.List; @@ -29,6 +29,9 @@ import jakarta.json.JsonValue; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.tls.config.TlsMutualConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfigBuilder; import io.aklivity.zilla.runtime.binding.tls.internal.TlsBinding; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; @@ -103,7 +106,7 @@ public JsonObject adaptToJson( } if (tlsOptions.mutual != null && - (tlsOptions.mutual != REQUIRED || tlsOptions.trust != null)) + (tlsOptions.trust == null || tlsOptions.mutual != REQUIRED)) { String mutual = tlsOptions.mutual.name().toLowerCase(); object.add(MUTUAL_NAME, mutual); @@ -123,32 +126,49 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - String version = object.containsKey(VERSION_NAME) - ? object.getString(VERSION_NAME) - : null; - List keys = object.containsKey(KEYS_NAME) - ? asListString(object.getJsonArray(KEYS_NAME)) - : null; - List trust = object.containsKey(TRUST_NAME) - ? asListString(object.getJsonArray(TRUST_NAME)) - : null; - boolean trustcacerts = object.containsKey(TRUSTCACERTS_NAME) - ? object.getBoolean(TRUSTCACERTS_NAME) - : false; - List sni = object.containsKey(SNI_NAME) - ? asListString(object.getJsonArray(SNI_NAME)) - : null; - List alpn = object.containsKey(ALPN_NAME) - ? asListString(object.getJsonArray(ALPN_NAME)) - : null; - TlsMutual mutual = object.containsKey(MUTUAL_NAME) - ? TlsMutual.valueOf(object.getString(MUTUAL_NAME).toUpperCase()) - : trust != null ? REQUIRED : null; - List signers = object.containsKey(SIGNERS_NAME) - ? asListString(object.getJsonArray(SIGNERS_NAME)) - : null; - - return new TlsOptionsConfig(version, keys, trust, sni, alpn, mutual, signers, trustcacerts); + TlsOptionsConfigBuilder tlsOptions = TlsOptionsConfig.builder(); + + if (object.containsKey(VERSION_NAME)) + { + tlsOptions.version(object.getString(VERSION_NAME)); + } + + if (object.containsKey(KEYS_NAME)) + { + tlsOptions.keys(asListString(object.getJsonArray(KEYS_NAME))); + } + + if (object.containsKey(TRUST_NAME)) + { + tlsOptions.trust(asListString(object.getJsonArray(TRUST_NAME))); + } + + if (object.containsKey(TRUSTCACERTS_NAME)) + { + tlsOptions.trustcacerts(object.getBoolean(TRUSTCACERTS_NAME)); + } + + if (object.containsKey(SNI_NAME)) + { + tlsOptions.sni(asListString(object.getJsonArray(SNI_NAME))); + } + + if (object.containsKey(ALPN_NAME)) + { + tlsOptions.alpn(asListString(object.getJsonArray(ALPN_NAME))); + } + + if (object.containsKey(MUTUAL_NAME)) + { + tlsOptions.mutual(TlsMutualConfig.valueOf(object.getString(MUTUAL_NAME).toUpperCase())); + } + + if (object.containsKey(SIGNERS_NAME)) + { + tlsOptions.signers(asListString(object.getJsonArray(SIGNERS_NAME))); + } + + return tlsOptions.build(); } private static List asListString( diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsRouteConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsRouteConfig.java index 6893b4dbce..180d8abc8d 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsRouteConfig.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsRouteConfig.java @@ -20,10 +20,10 @@ import java.util.List; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.tls.config.TlsConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class TlsRouteConfig extends OptionsConfig +public final class TlsRouteConfig { public final long id; diff --git a/runtime/binding-tls/src/main/moditect/module-info.java b/runtime/binding-tls/src/main/moditect/module-info.java index 13b4b0648d..194599b35c 100644 --- a/runtime/binding-tls/src/main/moditect/module-info.java +++ b/runtime/binding-tls/src/main/moditect/module-info.java @@ -19,6 +19,8 @@ requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.tls.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.tls.internal.TlsBindingFactorySpi; diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapterTest.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapterTest.java index 1f9b8963d6..a53a9b2a37 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapterTest.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsConditionConfigAdapterTest.java @@ -15,6 +15,7 @@ */ package io.aklivity.zilla.runtime.binding.tls.internal.config; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -27,6 +28,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.tls.config.TlsConditionConfig; + public class TlsConditionConfigAdapterTest { private Jsonb jsonb; @@ -58,7 +61,11 @@ public void shouldReadCondition() @Test public void shouldWriteCondition() { - TlsConditionConfig condition = new TlsConditionConfig("example.net", "echo"); + TlsConditionConfig condition = TlsConditionConfig.builder() + .inject(identity()) + .authority("example.net") + .alpn("echo") + .build(); String text = jsonb.toJson(condition); diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapterTest.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapterTest.java index 5fba85502e..832cd391b4 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapterTest.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsOptionsConfigAdapterTest.java @@ -15,8 +15,9 @@ */ package io.aklivity.zilla.runtime.binding.tls.internal.config; -import static io.aklivity.zilla.runtime.binding.tls.internal.config.TlsMutual.REQUESTED; +import static io.aklivity.zilla.runtime.binding.tls.config.TlsMutualConfig.REQUESTED; import static java.util.Arrays.asList; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -29,6 +30,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfig; + public class TlsOptionsConfigAdapterTest { private Jsonb jsonb; @@ -58,7 +61,10 @@ public void shouldReadOptions() @Test public void shouldWriteOptions() { - TlsOptionsConfig options = new TlsOptionsConfig("TLSv1.2", null, null, null, null, null, null, false); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .version("TLSv1.2") + .build(); String text = jsonb.toJson(options); @@ -83,7 +89,10 @@ public void shouldReadOptionsWithKeys() @Test public void shouldWriteOptionsWithKeys() { - TlsOptionsConfig options = new TlsOptionsConfig(null, asList("localhost"), null, null, null, null, null, false); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .keys(asList("localhost")) + .build(); String text = jsonb.toJson(options); @@ -108,7 +117,10 @@ public void shouldReadOptionsWithTrust() @Test public void shouldWriteOptionsWithTrust() { - TlsOptionsConfig options = new TlsOptionsConfig(null, null, asList("serverca"), null, null, null, null, false); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .trust(asList("serverca")) + .build(); String text = jsonb.toJson(options); @@ -133,7 +145,10 @@ public void shouldReadOptionsWithTrustcacerts() @Test public void shouldWriteOptionsWithTrustcacerts() { - TlsOptionsConfig options = new TlsOptionsConfig(null, null, null, null, null, null, null, true); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .trustcacerts(true) + .build(); String text = jsonb.toJson(options); @@ -158,7 +173,10 @@ public void shouldReadOptionsWithServerName() @Test public void shouldWriteOptionsWithServerName() { - TlsOptionsConfig options = new TlsOptionsConfig(null, null, null, asList("example.net"), null, null, null, false); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .sni(asList("example.net")) + .build(); String text = jsonb.toJson(options); @@ -183,7 +201,10 @@ public void shouldReadOptionsWithAlpn() @Test public void shouldWriteOptionsWithAlpn() { - TlsOptionsConfig options = new TlsOptionsConfig(null, null, null, null, asList("echo"), null, null, false); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .alpn(asList("echo")) + .build(); String text = jsonb.toJson(options); @@ -208,7 +229,10 @@ public void shouldReadOptionsWithMutual() @Test public void shouldWriteOptionsWithMutual() { - TlsOptionsConfig options = new TlsOptionsConfig(null, null, null, null, null, REQUESTED, null, false); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .mutual(REQUESTED) + .build(); String text = jsonb.toJson(options); @@ -233,8 +257,10 @@ public void shouldReadOptionsWithSigners() @Test public void shouldWriteOptionsWithSigners() { - TlsOptionsConfig options = - new TlsOptionsConfig(null, null, null, null, null, null, asList("clientca"), false); + TlsOptionsConfig options = TlsOptionsConfig.builder() + .inject(identity()) + .signers(asList("clientca")) + .build(); String text = jsonb.toJson(options); diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientFragmentedIT.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientFragmentedIT.java index 0486228556..b0fee23e02 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientFragmentedIT.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientFragmentedIT.java @@ -42,9 +42,7 @@ public class ClientFragmentedIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tls/config") .external("net0") .clean(); diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientIT.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientIT.java index 6f27c43510..bdbdd0d0de 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientIT.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ClientIT.java @@ -46,9 +46,7 @@ public class ClientIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tls/config") .external("net0") .configure(ENGINE_DRAIN_ON_CLOSE, false) @@ -264,6 +262,7 @@ public void shouldReceiveClientSentWriteCloseBeforeHandshake() throws Exception k3po.finish(); } + @Ignore("GitHub Actions") @Test @Configuration("client.yaml") @Specification({ diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ProxyIT.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ProxyIT.java index b8e06602b8..27ff2ac5dd 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ProxyIT.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ProxyIT.java @@ -39,9 +39,7 @@ public class ProxyIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tls/config") .external("net1") .configure(ENGINE_DRAIN_ON_CLOSE, false) diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerFragmentedIT.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerFragmentedIT.java index d6a09c8cf2..0dfc80fdb1 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerFragmentedIT.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerFragmentedIT.java @@ -42,9 +42,7 @@ public class ServerFragmentedIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tls/config") .external("app0") .clean(); diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerIT.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerIT.java index f2e7e80527..27ece98ddb 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerIT.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/streams/ServerIT.java @@ -44,9 +44,7 @@ public class ServerIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/binding/tls/config") .external("app0") .configure(ENGINE_DRAIN_ON_CLOSE, false) diff --git a/runtime/binding-ws/pom.xml b/runtime/binding-ws/pom.xml index 1946115e68..1ca326fb8e 100644 --- a/runtime/binding-ws/pom.xml +++ b/runtime/binding-ws/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfig.java b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/config/WsConditionConfig.java similarity index 94% rename from runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfig.java rename to runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/config/WsConditionConfig.java index 5b56f05579..c312415b84 100644 --- a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfig.java +++ b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/config/WsConditionConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.ws.internal.config; +package io.aklivity.zilla.runtime.binding.ws.config; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; diff --git a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfig.java b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/config/WsOptionsConfig.java similarity index 94% rename from runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfig.java rename to runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/config/WsOptionsConfig.java index b6b9e4f4a7..3a20767422 100644 --- a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfig.java +++ b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/config/WsOptionsConfig.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.binding.ws.internal.config; +package io.aklivity.zilla.runtime.binding.ws.config; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; diff --git a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsBindingConfig.java b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsBindingConfig.java index 36a5005258..7dbb3982b8 100644 --- a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsBindingConfig.java +++ b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsBindingConfig.java @@ -19,6 +19,7 @@ import java.util.List; +import io.aklivity.zilla.runtime.binding.ws.config.WsOptionsConfig; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; diff --git a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapter.java b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapter.java index febc29cb17..1b7946e73e 100644 --- a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapter.java +++ b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.ws.config.WsConditionConfig; import io.aklivity.zilla.runtime.binding.ws.internal.WsBinding; import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; diff --git a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionMatcher.java b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionMatcher.java index a37a8a7f42..62b4439f2a 100644 --- a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionMatcher.java +++ b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionMatcher.java @@ -18,6 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.aklivity.zilla.runtime.binding.ws.config.WsConditionConfig; + public final class WsConditionMatcher { private final Matcher protocol; diff --git a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapter.java b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapter.java index c89a0bcae7..2732f5c28b 100644 --- a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapter.java +++ b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapter.java @@ -20,6 +20,7 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.binding.ws.config.WsOptionsConfig; import io.aklivity.zilla.runtime.binding.ws.internal.WsBinding; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; diff --git a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsRouteConfig.java b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsRouteConfig.java index 2fc17f7ceb..eeadbc1c9b 100644 --- a/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsRouteConfig.java +++ b/runtime/binding-ws/src/main/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsRouteConfig.java @@ -20,10 +20,10 @@ import java.util.List; import java.util.function.LongPredicate; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.binding.ws.config.WsConditionConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -public final class WsRouteConfig extends OptionsConfig +public final class WsRouteConfig { public final long id; public final int order; diff --git a/runtime/binding-ws/src/main/moditect/module-info.java b/runtime/binding-ws/src/main/moditect/module-info.java index fe4c546064..9ac95ddcde 100644 --- a/runtime/binding-ws/src/main/moditect/module-info.java +++ b/runtime/binding-ws/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.binding.ws.config; + provides io.aklivity.zilla.runtime.engine.binding.BindingFactorySpi with io.aklivity.zilla.runtime.binding.ws.internal.WsBindingFactorySpi; diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapterTest.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapterTest.java index 352300272e..a9f3607b42 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapterTest.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsConditionConfigAdapterTest.java @@ -27,6 +27,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.ws.config.WsConditionConfig; + public class WsConditionConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapterTest.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapterTest.java index 07d2c18044..2eeb6c7053 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapterTest.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/config/WsOptionsConfigAdapterTest.java @@ -27,6 +27,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.binding.ws.config.WsOptionsConfig; + public class WsOptionsConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/AdvisoryIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/AdvisoryIT.java index 61f41b39a1..f7d22301f7 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/AdvisoryIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/AdvisoryIT.java @@ -42,9 +42,7 @@ public class AdvisoryIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("net0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/BaseFramingIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/BaseFramingIT.java index e4e18ec9a2..ec8640c9b1 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/BaseFramingIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/BaseFramingIT.java @@ -43,9 +43,7 @@ public class BaseFramingIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("net0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/FlowControlIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/FlowControlIT.java index 8a19a9eaed..7436b35fba 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/FlowControlIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/FlowControlIT.java @@ -42,9 +42,7 @@ public class FlowControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("net0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/OpeningHandshakeIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/OpeningHandshakeIT.java index e0983e7cc9..5ede78693e 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/OpeningHandshakeIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/client/OpeningHandshakeIT.java @@ -43,9 +43,7 @@ public class OpeningHandshakeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("net0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/AdvisoryIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/AdvisoryIT.java index 8af1531700..11d89fc600 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/AdvisoryIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/AdvisoryIT.java @@ -43,9 +43,7 @@ public class AdvisoryIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("app0") .configure(ENGINE_DRAIN_ON_CLOSE, false) diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/BaseFramingIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/BaseFramingIT.java index 00d61bb949..9f45297f91 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/BaseFramingIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/BaseFramingIT.java @@ -43,9 +43,7 @@ public class BaseFramingIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("app0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ClosingHandshakeIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ClosingHandshakeIT.java index feb11c905f..9b9a8db51e 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ClosingHandshakeIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ClosingHandshakeIT.java @@ -42,9 +42,7 @@ public class ClosingHandshakeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("app0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ControlIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ControlIT.java index deacfca40c..b56df19049 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ControlIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/ControlIT.java @@ -40,9 +40,7 @@ public class ControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("app0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FlowControlIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FlowControlIT.java index 70ed155911..4c3d957554 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FlowControlIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FlowControlIT.java @@ -43,9 +43,7 @@ public class FlowControlIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("app0") .configure(ENGINE_DRAIN_ON_CLOSE, false) diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FragmentationIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FragmentationIT.java index fb021c3d29..5c588bdd56 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FragmentationIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/FragmentationIT.java @@ -42,9 +42,7 @@ public class FragmentationIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("app0") .clean(); diff --git a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/OpeningHandshakeIT.java b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/OpeningHandshakeIT.java index 3616f47656..e6e1a55938 100644 --- a/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/OpeningHandshakeIT.java +++ b/runtime/binding-ws/src/test/java/io/aklivity/zilla/runtime/binding/ws/internal/streams/server/OpeningHandshakeIT.java @@ -43,9 +43,7 @@ public class OpeningHandshakeIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/binding/ws/config") .external("app0") .clean(); diff --git a/runtime/command-metrics/pom.xml b/runtime/command-metrics/pom.xml index d5526d424c..cd972027f1 100644 --- a/runtime/command-metrics/pom.xml +++ b/runtime/command-metrics/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml @@ -28,7 +28,6 @@ 11 0.50 2 - 4.9.0 @@ -52,7 +51,6 @@ org.mockito mockito-core - ${mockito.version} test diff --git a/runtime/command-start/pom.xml b/runtime/command-start/pom.xml index 36fedfcfad..88b6fad84b 100644 --- a/runtime/command-start/pom.xml +++ b/runtime/command-start/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/command-start/src/main/java/io/aklivity/zilla/runtime/command/start/internal/airline/ZillaStartCommand.java b/runtime/command-start/src/main/java/io/aklivity/zilla/runtime/command/start/internal/airline/ZillaStartCommand.java index 9a56e2e41d..1cbb02786c 100644 --- a/runtime/command-start/src/main/java/io/aklivity/zilla/runtime/command/start/internal/airline/ZillaStartCommand.java +++ b/runtime/command-start/src/main/java/io/aklivity/zilla/runtime/command/start/internal/airline/ZillaStartCommand.java @@ -176,6 +176,7 @@ public void run() catch (Throwable ex) { System.out.println("error"); + onError.onError(ex); rethrowUnchecked(ex); } } diff --git a/runtime/command-stop/pom.xml b/runtime/command-stop/pom.xml index 00346ebadc..359ac57da4 100644 --- a/runtime/command-stop/pom.xml +++ b/runtime/command-stop/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/command/pom.xml b/runtime/command/pom.xml index a56e5cb702..ca31d008d9 100644 --- a/runtime/command/pom.xml +++ b/runtime/command/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/engine/NOTICE b/runtime/engine/NOTICE index 026266af23..212f9654aa 100644 --- a/runtime/engine/NOTICE +++ b/runtime/engine/NOTICE @@ -14,9 +14,14 @@ under the License. This project includes: agrona under The Apache License, Version 2.0 ICU4J under Unicode/ICU License + Jackson-annotations under The Apache Software License, Version 2.0 + Jackson-core under The Apache Software License, Version 2.0 + jackson-databind under The Apache Software License, Version 2.0 + Jackson-dataformat-YAML under The Apache Software License, Version 2.0 Jakarta JSON Processing API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception JSON-B API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception org.leadpony.justify under The Apache Software License, Version 2.0 + SnakeYAML under Apache License, Version 2.0 This project also includes code under copyright of the following entities: diff --git a/runtime/engine/pom.xml b/runtime/engine/pom.xml index 10e1815461..9a37064f60 100644 --- a/runtime/engine/pom.xml +++ b/runtime/engine/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml @@ -69,6 +69,11 @@ + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + 2.15.2 + org.jmock jmock-junit4 diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/Configuration.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/Configuration.java index 3879d5fcd9..5be98c3238 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/Configuration.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/Configuration.java @@ -214,14 +214,14 @@ public CharPropertyDef property( public PropertyDef property( String name) { - return property(String.class, name, identity(), c -> null); + return property(String.class, name, identity(), (String) null); } public PropertyDef property( String name, String defaultValue) { - return property(String.class, name, identity(), c -> defaultValue); + return property(String.class, name, identity(), defaultValue); } public PropertyDef property( @@ -231,6 +231,18 @@ public PropertyDef property( return property(String.class, name, identity(), defaultValue); } + public PropertyDef property( + Class kind, + String name, + Function decodeValue, + T defaultValue) + { + String qualifiedName = qualifiedName(name); + PropertyDef property = new ObjectPropertyDef(kind, qualifiedName, decodeValue, defaultValue); + properties.put(qualifiedName, property); + return property; + } + public PropertyDef property( Class kind, String name, diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineConfiguration.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineConfiguration.java index 6bdc7840ec..7c9bc53e24 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineConfiguration.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineConfiguration.java @@ -34,6 +34,8 @@ import org.agrona.LangUtil; +import io.aklivity.zilla.runtime.engine.internal.layouts.BudgetsLayout; + public class EngineConfiguration extends Configuration { public static final boolean DEBUG_BUDGETS = Boolean.getBoolean("zilla.engine.debug.budgets"); @@ -44,15 +46,12 @@ public class EngineConfiguration extends Configuration public static final PropertyDef ENGINE_DIRECTORY; public static final PropertyDef ENGINE_CACHE_DIRECTORY; public static final PropertyDef ENGINE_HOST_RESOLVER; - public static final IntPropertyDef ENGINE_BUDGETS_BUFFER_CAPACITY; - public static final IntPropertyDef ENGINE_LOAD_BUFFER_CAPACITY; - public static final IntPropertyDef ENGINE_STREAMS_BUFFER_CAPACITY; - public static final IntPropertyDef ENGINE_COMMAND_BUFFER_CAPACITY; - public static final IntPropertyDef ENGINE_RESPONSE_BUFFER_CAPACITY; - public static final IntPropertyDef ENGINE_COUNTERS_BUFFER_CAPACITY; + public static final IntPropertyDef ENGINE_WORKER_CAPACITY; public static final IntPropertyDef ENGINE_BUFFER_POOL_CAPACITY; public static final IntPropertyDef ENGINE_BUFFER_SLOT_CAPACITY; - public static final IntPropertyDef ENGINE_ROUTES_BUFFER_CAPACITY; + public static final IntPropertyDef ENGINE_STREAMS_BUFFER_CAPACITY; + public static final IntPropertyDef ENGINE_COUNTERS_BUFFER_CAPACITY; + public static final IntPropertyDef ENGINE_BUDGETS_BUFFER_CAPACITY; public static final BooleanPropertyDef ENGINE_TIMESTAMPS; public static final IntPropertyDef ENGINE_MAXIMUM_MESSAGES_PER_READ; public static final IntPropertyDef ENGINE_MAXIMUM_EXPIRATIONS_PER_POLL; @@ -83,24 +82,22 @@ public class EngineConfiguration extends Configuration ENGINE_CACHE_DIRECTORY = config.property(Path.class, "cache.directory", EngineConfiguration::cacheDirectory, "cache"); ENGINE_HOST_RESOLVER = config.property(HostResolver.class, "host.resolver", EngineConfiguration::decodeHostResolver, EngineConfiguration::defaultHostResolver); - ENGINE_BUDGETS_BUFFER_CAPACITY = config.property("budgets.buffer.capacity", 1024 * 1024); - ENGINE_LOAD_BUFFER_CAPACITY = config.property("load.buffer.capacity", 1024 * 8); - ENGINE_STREAMS_BUFFER_CAPACITY = config.property("streams.buffer.capacity", 1024 * 1024); - ENGINE_COMMAND_BUFFER_CAPACITY = config.property("command.buffer.capacity", 1024 * 1024); - ENGINE_RESPONSE_BUFFER_CAPACITY = config.property("response.buffer.capacity", 1024 * 1024); - ENGINE_COUNTERS_BUFFER_CAPACITY = config.property("counters.buffer.capacity", 1024 * 1024); + ENGINE_WORKER_CAPACITY = config.property("worker.capacity", 64); ENGINE_BUFFER_POOL_CAPACITY = config.property("buffer.pool.capacity", EngineConfiguration::defaultBufferPoolCapacity); ENGINE_BUFFER_SLOT_CAPACITY = config.property("buffer.slot.capacity", 64 * 1024); - ENGINE_ROUTES_BUFFER_CAPACITY = config.property("routes.buffer.capacity", 1024 * 1024); + ENGINE_STREAMS_BUFFER_CAPACITY = config.property("streams.buffer.capacity", + EngineConfiguration::defaultStreamsBufferCapacity); + ENGINE_BUDGETS_BUFFER_CAPACITY = config.property("budgets.buffer.capacity", + EngineConfiguration::defaultBudgetsBufferCapacity); + ENGINE_COUNTERS_BUFFER_CAPACITY = config.property("counters.buffer.capacity", 1024 * 1024); ENGINE_TIMESTAMPS = config.property("timestamps", true); ENGINE_MAXIMUM_MESSAGES_PER_READ = config.property("maximum.messages.per.read", Integer.MAX_VALUE); ENGINE_MAXIMUM_EXPIRATIONS_PER_POLL = config.property("maximum.expirations.per.poll", Integer.MAX_VALUE); ENGINE_TASK_PARALLELISM = config.property("task.parallelism", 1); ENGINE_BACKOFF_MAX_SPINS = config.property("backoff.idle.strategy.max.spins", 64L); ENGINE_BACKOFF_MAX_YIELDS = config.property("backoff.idle.strategy.max.yields", 64L); - // TODO: shorten property name string values to match constant naming - ENGINE_BACKOFF_MIN_PARK_NANOS = config.property("backoff.idle.strategy.min.park.period", NANOSECONDS.toNanos(64L)); - ENGINE_BACKOFF_MAX_PARK_NANOS = config.property("backoff.idle.strategy.max.park.period", MILLISECONDS.toNanos(1L)); + ENGINE_BACKOFF_MIN_PARK_NANOS = config.property("backoff.min.park.nanos", NANOSECONDS.toNanos(64L)); + ENGINE_BACKOFF_MAX_PARK_NANOS = config.property("backoff.max.park.nanos", MILLISECONDS.toNanos(100L)); ENGINE_DRAIN_ON_CLOSE = config.property("drain.on.close", false); ENGINE_SYNTHETIC_ABORT = config.property("synthetic.abort", false); ENGINE_ROUTED_DELAY_MILLIS = config.property("routed.delay.millis", 0L); @@ -172,26 +169,6 @@ public int bufferSlotCapacity() return ENGINE_BUFFER_SLOT_CAPACITY.getAsInt(this); } - public int maximumStreamsCount() - { - return bufferPoolCapacity() / bufferSlotCapacity(); - } - - public int maximumMessagesPerRead() - { - return ENGINE_MAXIMUM_MESSAGES_PER_READ.getAsInt(this); - } - - public int maximumExpirationsPerPoll() - { - return ENGINE_MAXIMUM_EXPIRATIONS_PER_POLL.getAsInt(this); - } - - public int taskParallelism() - { - return ENGINE_TASK_PARALLELISM.getAsInt(this); - } - public int budgetsBufferCapacity() { return ENGINE_BUDGETS_BUFFER_CAPACITY.getAsInt(this); @@ -202,39 +179,24 @@ public int streamsBufferCapacity() return ENGINE_STREAMS_BUFFER_CAPACITY.getAsInt(this); } - public int commandBufferCapacity() + public int countersBufferCapacity() { - return ENGINE_COMMAND_BUFFER_CAPACITY.get(this); - } - - public int responseBufferCapacity() - { - return ENGINE_RESPONSE_BUFFER_CAPACITY.getAsInt(this); - } - - public int loadBufferCapacity() - { - return ENGINE_LOAD_BUFFER_CAPACITY.getAsInt(this); - } - - public int routesBufferCapacity() - { - return ENGINE_ROUTES_BUFFER_CAPACITY.get(this); + return ENGINE_COUNTERS_BUFFER_CAPACITY.getAsInt(this); } - public int counterBufferCapacity() + public int maximumMessagesPerRead() { - return ENGINE_COUNTERS_BUFFER_CAPACITY.getAsInt(this); + return ENGINE_MAXIMUM_MESSAGES_PER_READ.getAsInt(this); } - public int counterValuesBufferCapacity() + public int maximumExpirationsPerPoll() { - return ENGINE_COUNTERS_BUFFER_CAPACITY.getAsInt(this); + return ENGINE_MAXIMUM_EXPIRATIONS_PER_POLL.getAsInt(this); } - public int counterLabelsBufferCapacity() + public int taskParallelism() { - return ENGINE_COUNTERS_BUFFER_CAPACITY.getAsInt(this) * 2; + return ENGINE_TASK_PARALLELISM.getAsInt(this); } public boolean timestamps() @@ -310,7 +272,20 @@ public Function hostResolver() private static int defaultBufferPoolCapacity( Configuration config) { - return ENGINE_BUFFER_SLOT_CAPACITY.get(config) * 64; + return ENGINE_BUFFER_SLOT_CAPACITY.get(config) * ENGINE_WORKER_CAPACITY.getAsInt(config); + } + + private static int defaultStreamsBufferCapacity( + Configuration config) + { + return ENGINE_BUFFER_SLOT_CAPACITY.get(config) * ENGINE_WORKER_CAPACITY.getAsInt(config); + } + + private static int defaultBudgetsBufferCapacity( + Configuration config) + { + // more consistent with original defaults + return BudgetsLayout.SIZEOF_BUDGET_ENTRY * 512 * ENGINE_WORKER_CAPACITY.getAsInt(config); } private static URL configURL( diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/AttributeConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/AttributeConfig.java index db8b662fc1..66b9f2184e 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/AttributeConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/AttributeConfig.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; public class AttributeConfig { @@ -24,7 +25,12 @@ public class AttributeConfig public final String name; public final String value; - public AttributeConfig( + public static AttributeConfigBuilder builder() + { + return new AttributeConfigBuilder<>(identity()); + } + + AttributeConfig( String name, String value) { diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/AttributeConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/AttributeConfigBuilder.java new file mode 100644 index 0000000000..9cd42de88f --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/AttributeConfigBuilder.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.function.Function; + +public final class AttributeConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String name; + private String value; + + AttributeConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public AttributeConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public AttributeConfigBuilder value( + String value) + { + this.value = value; + return this; + } + + public T build() + { + return mapper.apply(new AttributeConfig(name, value)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/BindingConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/BindingConfig.java index d5a597db6f..1ce100f0b9 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/BindingConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/BindingConfig.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; import java.util.List; import java.util.function.ToLongFunction; @@ -39,7 +40,12 @@ public class BindingConfig public final List routes; public final TelemetryRefConfig telemetryRef; - public BindingConfig( + public static BindingConfigBuilder builder() + { + return new BindingConfigBuilder<>(identity()); + } + + BindingConfig( String vault, String name, String type, diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/BindingConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/BindingConfigBuilder.java new file mode 100644 index 0000000000..50aa0863c4 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/BindingConfigBuilder.java @@ -0,0 +1,161 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static java.util.Collections.emptyList; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public final class BindingConfigBuilder extends ConfigBuilder> +{ + public static final List ROUTES_DEFAULT = emptyList(); + + private final Function mapper; + + private String vault; + private String name; + private String type; + private KindConfig kind; + private String entry; + private String exit; + private OptionsConfig options; + private List routes; + private TelemetryRefConfig telemetry; + + BindingConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public BindingConfigBuilder vault( + String vault) + { + this.vault = vault; + return this; + } + + public BindingConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public BindingConfigBuilder type( + String type) + { + this.type = type; + return this; + } + + public BindingConfigBuilder kind( + KindConfig kind) + { + this.kind = kind; + return this; + } + + public BindingConfigBuilder entry( + String entry) + { + this.entry = entry; + return this; + } + + public BindingConfigBuilder exit( + String exit) + { + this.exit = exit; + return this; + } + + public , C>> C options( + Function>, C> options) + { + return options.apply(this::options); + } + + public BindingConfigBuilder options( + OptionsConfig options) + { + this.options = options; + return this; + } + + public RouteConfigBuilder> route() + { + return new RouteConfigBuilder<>(this::route) + .order(routes != null ? routes.size() : 0); + } + + public BindingConfigBuilder route( + RouteConfig route) + { + if (routes == null) + { + routes = new LinkedList<>(); + } + + assert route.order == routes.size(); + + routes.add(route); + return this; + } + + public TelemetryRefConfigBuilder> telemetry() + { + return new TelemetryRefConfigBuilder<>(this::telemetry); + } + + public BindingConfigBuilder telemetry( + TelemetryRefConfig telemetry) + { + this.telemetry = telemetry; + return this; + } + + @Override + public T build() + { + if (exit != null) + { + route() + .exit(exit) + .build(); + } + + return mapper.apply(new BindingConfig( + vault, + name, + type, + kind, + entry, + options, + Optional.ofNullable(routes).orElse(ROUTES_DEFAULT), + telemetry)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigBuilder.java new file mode 100644 index 0000000000..7354593168 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigBuilder.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.function.Function; + +public abstract class ConfigBuilder> +{ + protected abstract Class thisType(); + + public final R inject( + Function visitor) + { + return visitor.apply(thisType().cast(this)); + } + + public abstract T build(); +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigException.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigException.java new file mode 100644 index 0000000000..c22bed5226 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigException.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +public final class ConfigException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public ConfigException( + String message) + { + super(message); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigReader.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigReader.java new file mode 100644 index 0000000000..8e22e20cf5 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigReader.java @@ -0,0 +1,150 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static jakarta.json.stream.JsonGenerator.PRETTY_PRINTING; +import static java.util.Collections.singletonMap; +import static org.agrona.LangUtil.rethrowUnchecked; + +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URL; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Consumer; + +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonReader; +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonParser; + +import org.leadpony.justify.api.JsonSchema; +import org.leadpony.justify.api.JsonSchemaReader; +import org.leadpony.justify.api.JsonValidationService; +import org.leadpony.justify.api.ProblemHandler; + +import io.aklivity.zilla.runtime.engine.Engine; +import io.aklivity.zilla.runtime.engine.internal.config.NamespaceAdapter; +import io.aklivity.zilla.runtime.engine.internal.config.schema.UniquePropertyKeysSchema; + +public final class ConfigReader +{ + private final ConfigAdapterContext context; + private final Collection schemaTypes; + private final Consumer logger; + + public ConfigReader( + ConfigAdapterContext context, + Collection schemaTypes, + Consumer logger) + { + this.context = context; + this.schemaTypes = schemaTypes; + this.logger = logger; + } + + public NamespaceConfig read( + Reader reader) + { + NamespaceConfig namespace = null; + + List errors = new LinkedList<>(); + + read: + try + { + InputStream schemaInput = Engine.class.getResourceAsStream("internal/schema/engine.schema.json"); + + JsonProvider schemaProvider = JsonProvider.provider(); + JsonReader schemaReader = schemaProvider.createReader(schemaInput); + JsonObject schemaObject = schemaReader.readObject(); + + for (URL schemaType : schemaTypes) + { + InputStream schemaPatchInput = schemaType.openStream(); + JsonReader schemaPatchReader = schemaProvider.createReader(schemaPatchInput); + JsonArray schemaPatchArray = schemaPatchReader.readArray(); + JsonPatch schemaPatch = schemaProvider.createPatch(schemaPatchArray); + + schemaObject = schemaPatch.apply(schemaObject); + } + + if (logger != null) + { + final StringWriter out = new StringWriter(); + schemaProvider.createGeneratorFactory(singletonMap(PRETTY_PRINTING, true)) + .createGenerator(out) + .write(schemaObject) + .close(); + + final String schemaText = out.getBuffer().toString(); + logger.accept(schemaText); + } + + JsonParser schemaParser = schemaProvider.createParserFactory(null) + .createParser(new StringReader(schemaObject.toString())); + + JsonValidationService service = JsonValidationService.newInstance(); + ProblemHandler handler = service.createProblemPrinter(msg -> errors.add(new ConfigException(msg))); + JsonSchemaReader validator = service.createSchemaReader(schemaParser); + JsonSchema schema = new UniquePropertyKeysSchema(validator.read()); + + JsonProvider provider = service.createJsonProvider(schema, parser -> handler); + provider.createReader(reader).read(); + + if (!errors.isEmpty()) + { + break read; + } + + JsonbConfig config = new JsonbConfig() + .withAdapters(new NamespaceAdapter(context)); + Jsonb jsonb = JsonbBuilder.newBuilder() + .withProvider(provider) + .withConfig(config) + .build(); + + reader.reset(); + namespace = jsonb.fromJson(reader, NamespaceConfig.class); + + if (!errors.isEmpty()) + { + break read; + } + } + catch (Exception ex) + { + errors.add(ex); + } + + if (!errors.isEmpty()) + { + Exception ex = errors.remove(0); + errors.forEach(ex::addSuppressed); + rethrowUnchecked(ex); + } + + return namespace; + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigWriter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigWriter.java new file mode 100644 index 0000000000..dd45f7abd5 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ConfigWriter.java @@ -0,0 +1,140 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature.MINIMIZE_QUOTES; +import static com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature.WRITE_DOC_START_MARKER; +import static org.agrona.LangUtil.rethrowUnchecked; + +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.LinkedList; +import java.util.List; + +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonValue; +import jakarta.json.JsonWriter; +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; +import jakarta.json.spi.JsonProvider; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; + +import io.aklivity.zilla.runtime.engine.internal.config.NamespaceAdapter; + +public final class ConfigWriter +{ + private static final JsonPatch NOOP_PATCH = JsonProvider.provider().createPatch(JsonValue.EMPTY_JSON_ARRAY); + + private final ConfigAdapterContext context; + + public ConfigWriter( + ConfigAdapterContext context) + { + this.context = context; + } + + public void write( + NamespaceConfig namespace, + Writer writer) + { + write0(namespace, writer, NOOP_PATCH); + } + + public void write( + NamespaceConfig namespace, + Writer writer, + JsonPatch patch) + { + write0(namespace, writer, patch); + } + + public String write( + NamespaceConfig namespace) + { + StringWriter writer = new StringWriter(); + write0(namespace, writer, NOOP_PATCH); + return writer.toString(); + } + + public String write( + NamespaceConfig namespace, + JsonPatch patch) + { + StringWriter writer = new StringWriter(); + write0(namespace, writer, patch); + return writer.toString(); + } + + private void write0( + NamespaceConfig namespace, + Writer writer, + JsonPatch patch) + { + List errors = new LinkedList<>(); + + write: + try + { + // TODO: YamlProvider (supporting YamlGenerator) + JsonProvider provider = JsonProvider.provider(); + + JsonbConfig config = new JsonbConfig() + .withAdapters(new NamespaceAdapter(context)) + .withFormatting(true); + Jsonb jsonb = JsonbBuilder.newBuilder() + .withProvider(provider) + .withConfig(config) + .build(); + String jsonText = jsonb.toJson(namespace, NamespaceConfig.class); + + JsonObject jsonObject = provider.createReader(new StringReader(jsonText)).readObject(); + JsonObject patched = patch.apply(jsonObject); + StringWriter patchedText = new StringWriter(); + JsonWriter jsonWriter = provider.createWriter(patchedText); + jsonWriter.write(patched); + String patchedJson = patchedText.toString(); + + JsonNode json = new ObjectMapper().readTree(patchedJson); + YAMLMapper mapper = YAMLMapper.builder() + .disable(WRITE_DOC_START_MARKER) + .enable(MINIMIZE_QUOTES) + .build(); + mapper.writeValue(writer, json); + + if (!errors.isEmpty()) + { + break write; + } + } + catch (Exception ex) + { + errors.add(ex); + } + + if (!errors.isEmpty()) + { + Exception ex = errors.remove(0); + errors.forEach(ex::addSuppressed); + rethrowUnchecked(ex); + } + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ExporterConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ExporterConfig.java index a40e4d7c56..20777fe25d 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ExporterConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ExporterConfig.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; public class ExporterConfig { @@ -25,7 +26,12 @@ public class ExporterConfig public transient long id; - public ExporterConfig( + public static ExporterConfigBuilder builder() + { + return new ExporterConfigBuilder<>(identity()); + } + + ExporterConfig( String name, String type, OptionsConfig options) diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ExporterConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ExporterConfigBuilder.java new file mode 100644 index 0000000000..1eb6db05b5 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/ExporterConfigBuilder.java @@ -0,0 +1,73 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.function.Function; + +public final class ExporterConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String name; + private String type; + private OptionsConfig options; + + ExporterConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public ExporterConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public ExporterConfigBuilder type( + String type) + { + this.type = type; + return this; + } + + public , C>> C options( + Function>, C> options) + { + return options.apply(this::options); + } + + public ExporterConfigBuilder options( + OptionsConfig options) + { + this.options = options; + return this; + } + + @Override + public T build() + { + return mapper.apply(new ExporterConfig(name, type, options)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardConfig.java index dacd3922da..fcd93b0055 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardConfig.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; import java.util.function.Function; @@ -28,7 +29,12 @@ public class GuardConfig public final String type; public final OptionsConfig options; - public GuardConfig( + public static final GuardConfigBuilder builder() + { + return new GuardConfigBuilder<>(identity()); + } + + GuardConfig( String name, String type, OptionsConfig options) diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardConfigBuilder.java new file mode 100644 index 0000000000..9b441e35b1 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardConfigBuilder.java @@ -0,0 +1,73 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.function.Function; + +public final class GuardConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String name; + private String type; + private OptionsConfig options; + + GuardConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public GuardConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public GuardConfigBuilder type( + String type) + { + this.type = type; + return this; + } + + public , C>> C options( + Function>, C> options) + { + return options.apply(this::options); + } + + public GuardConfigBuilder options( + OptionsConfig options) + { + this.options = options; + return this; + } + + @Override + public T build() + { + return mapper.apply(new GuardConfig(name, type, options)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardedConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardedConfig.java index dad66c3204..4c0f91c419 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardedConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardedConfig.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; import java.util.List; import java.util.function.LongFunction; @@ -28,7 +29,12 @@ public class GuardedConfig public final String name; public final List roles; - public GuardedConfig( + public static GuardedConfigBuilder builder() + { + return new GuardedConfigBuilder<>(identity()); + } + + GuardedConfig( String name, List roles) { diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardedConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardedConfigBuilder.java new file mode 100644 index 0000000000..66213bfc09 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/GuardedConfigBuilder.java @@ -0,0 +1,72 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static java.util.Collections.emptyList; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public final class GuardedConfigBuilder extends ConfigBuilder> +{ + public static final List ROLES_DEFAULT = emptyList(); + + private final Function mapper; + + private String name; + private List roles; + + GuardedConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public GuardedConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public GuardedConfigBuilder role( + String role) + { + if (roles == null) + { + roles = new LinkedList<>(); + } + roles.add(role); + return this; + } + + @Override + public T build() + { + return mapper.apply(new GuardedConfig( + name, + Optional.ofNullable(roles).orElse(ROLES_DEFAULT))); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricConfig.java index 3240ca3c54..2ad112c7e4 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricConfig.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; public class MetricConfig { @@ -24,7 +25,12 @@ public class MetricConfig public transient long id; - public MetricConfig( + public static MetricConfigBuilder builder() + { + return new MetricConfigBuilder<>(identity()); + } + + MetricConfig( String group, String name) { diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricConfigBuilder.java new file mode 100644 index 0000000000..34137b9f92 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricConfigBuilder.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.function.Function; + +public final class MetricConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String group; + private String name; + + MetricConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public MetricConfigBuilder group( + String group) + { + this.group = group; + return this; + } + + public MetricConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + @Override + public T build() + { + return mapper.apply(new MetricConfig(group, name)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricRefConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricRefConfig.java index 90339cb346..da6653c87b 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricRefConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricRefConfig.java @@ -16,12 +16,18 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; public class MetricRefConfig { public final String name; - public MetricRefConfig( + public static MetricRefConfigBuilder builder() + { + return new MetricRefConfigBuilder<>(identity()); + } + + MetricRefConfig( String name) { this.name = requireNonNull(name); diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricRefConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricRefConfigBuilder.java new file mode 100644 index 0000000000..712529c9d5 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/MetricRefConfigBuilder.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.function.Function; + +public final class MetricRefConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String name; + + MetricRefConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public MetricRefConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public T build() + { + return mapper.apply(new MetricRefConfig(name)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceConfig.java index 118857c1d9..afe2322cf2 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceConfig.java @@ -16,13 +16,12 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; import java.util.List; import java.util.function.Function; import java.util.function.ToLongFunction; -import io.aklivity.zilla.runtime.engine.internal.config.NamespaceRef; - public class NamespaceConfig { public transient int id; @@ -30,15 +29,20 @@ public class NamespaceConfig public transient Function readURL; public final String name; - public final List references; + public final List references; public final TelemetryConfig telemetry; public final List bindings; public final List guards; public final List vaults; - public NamespaceConfig( + public static NamespaceConfigBuilder builder() + { + return new NamespaceConfigBuilder<>(identity()); + } + + NamespaceConfig( String name, - List references, + List references, TelemetryConfig telemetry, List bindings, List guards, diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceConfigBuilder.java new file mode 100644 index 0000000000..68a2899d8f --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceConfigBuilder.java @@ -0,0 +1,169 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static java.util.Collections.emptyList; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public final class NamespaceConfigBuilder extends ConfigBuilder> +{ + public static final List NAMESPACES_DEFAULT = emptyList(); + public static final List BINDINGS_DEFAULT = emptyList(); + public static final List GUARDS_DEFAULT = emptyList(); + public static final List VAULTS_DEFAULT = emptyList(); + public static final TelemetryConfig TELEMETRY_DEFAULT = TelemetryConfig.EMPTY; + + private final Function mapper; + + private String name; + private List namespaces; + private TelemetryConfig telemetry; + private List bindings; + private List guards; + private List vaults; + + NamespaceConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public NamespaceConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public NamespaceRefConfigBuilder> namespace() + { + return new NamespaceRefConfigBuilder<>(this::namespace); + } + + public NamespaceConfigBuilder namespace( + NamespaceRefConfig namespace) + { + if (namespaces == null) + { + namespaces = new LinkedList<>(); + } + namespaces.add(namespace); + return this; + } + + public TelemetryConfigBuilder> telemetry() + { + return new TelemetryConfigBuilder<>(this::telemetry); + } + + public NamespaceConfigBuilder telemetry( + TelemetryConfig telemetry) + { + this.telemetry = telemetry; + return this; + } + + public BindingConfigBuilder> binding() + { + return new BindingConfigBuilder<>(this::binding); + } + + public NamespaceConfigBuilder binding( + BindingConfig binding) + { + if (bindings == null) + { + bindings = new LinkedList<>(); + } + bindings.add(binding); + return this; + } + + public NamespaceConfigBuilder bindings( + List bindings) + { + this.bindings = bindings; + return this; + } + + public GuardConfigBuilder> guard() + { + return new GuardConfigBuilder<>(this::guard); + } + + public NamespaceConfigBuilder guard( + GuardConfig guard) + { + if (guards == null) + { + guards = new LinkedList<>(); + } + guards.add(guard); + return this; + } + + public NamespaceConfigBuilder guards( + List guards) + { + this.guards = guards; + return this; + } + + public VaultConfigBuilder> vault() + { + return new VaultConfigBuilder<>(this::vault); + } + + public NamespaceConfigBuilder vault( + VaultConfig vault) + { + if (vaults == null) + { + vaults = new LinkedList<>(); + } + vaults.add(vault); + return this; + } + + public NamespaceConfigBuilder vaults( + List vaults) + { + this.vaults = vaults; + return this; + } + + public T build() + { + return mapper.apply(new NamespaceConfig( + name, + Optional.ofNullable(namespaces).orElse(NAMESPACES_DEFAULT), + Optional.ofNullable(telemetry).orElse(TELEMETRY_DEFAULT), + Optional.ofNullable(bindings).orElse(BINDINGS_DEFAULT), + Optional.ofNullable(guards).orElse(GUARDS_DEFAULT), + Optional.ofNullable(vaults).orElse(VAULTS_DEFAULT))); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceRefConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceRefConfig.java new file mode 100644 index 0000000000..9261dd32bc --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceRefConfig.java @@ -0,0 +1,39 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static java.util.function.Function.identity; + +import java.util.Map; + +public class NamespaceRefConfig +{ + public final String name; + public final Map links; + + public static NamespaceRefConfigBuilder builder() + { + return new NamespaceRefConfigBuilder<>(identity()); + } + + NamespaceRefConfig( + String name, + Map links) + { + this.name = name; + this.links = links; + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceRefConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceRefConfigBuilder.java new file mode 100644 index 0000000000..b49f33e45a --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/NamespaceRefConfigBuilder.java @@ -0,0 +1,74 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static java.util.Collections.emptyMap; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +public final class NamespaceRefConfigBuilder extends ConfigBuilder> +{ + public static final Map LINKS_DEFAULT = emptyMap(); + + private final Function mapper; + + private String name; + private Map links; + + NamespaceRefConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public NamespaceRefConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public NamespaceRefConfigBuilder link( + String name, + String value) + { + if (links == null) + { + links = new LinkedHashMap<>(); + } + links.put(name, value); + return this; + } + + @Override + public T build() + { + return mapper.apply(new NamespaceRefConfig( + name, + Optional.ofNullable(links).orElse(LINKS_DEFAULT))); + } + +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/RouteConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/RouteConfig.java index 1463acf76b..47b6d0511c 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/RouteConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/RouteConfig.java @@ -15,17 +15,14 @@ */ package io.aklivity.zilla.runtime.engine.config; -import static java.util.Collections.emptyList; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; import java.util.List; import java.util.function.LongPredicate; public class RouteConfig { - public static final List WHEN_DEFAULT = emptyList(); - public static final List GUARDED_DEFAULT = emptyList(); - public transient long id; public transient LongPredicate authorized; @@ -35,35 +32,12 @@ public class RouteConfig public final WithConfig with; public final List guarded; - public RouteConfig( - String exit) - { - this(0, exit); - } - - public RouteConfig( - String exit, - List guarded) - { - this(exit, WHEN_DEFAULT, guarded); - } - - public RouteConfig( - String exit, - List when, - List guarded) - { - this(0, exit, when, null, guarded); - } - - public RouteConfig( - int order, - String exit) + public static RouteConfigBuilder builder() { - this(order, exit, WHEN_DEFAULT, null, GUARDED_DEFAULT); + return new RouteConfigBuilder<>(identity()); } - public RouteConfig( + RouteConfig( int order, String exit, List when, diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/RouteConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/RouteConfigBuilder.java new file mode 100644 index 0000000000..0f7056ce50 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/RouteConfigBuilder.java @@ -0,0 +1,121 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static java.util.Collections.emptyList; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public final class RouteConfigBuilder extends ConfigBuilder> +{ + public static final List WHEN_DEFAULT = emptyList(); + public static final List GUARDED_DEFAULT = emptyList(); + + private final Function mapper; + + private int order; + private String exit; + private List when; + private WithConfig with; + private List guarded; + + RouteConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public RouteConfigBuilder order( + int order) + { + this.order = order; + return this; + } + + public RouteConfigBuilder exit( + String exit) + { + this.exit = exit; + return this; + } + + public , C>> C when( + Function>, C> condition) + { + return condition.apply(this::when); + } + + public RouteConfigBuilder when( + ConditionConfig condition) + { + if (when == null) + { + when = new LinkedList<>(); + } + when.add(condition); + return this; + } + + public , B>> B with( + Function>, B> with) + { + return with.apply(this::with); + } + + public RouteConfigBuilder with( + WithConfig with) + { + this.with = with; + return this; + } + + public GuardedConfigBuilder> guarded() + { + return new GuardedConfigBuilder<>(this::guarded); + } + + public RouteConfigBuilder guarded( + GuardedConfig guarded) + { + if (this.guarded == null) + { + this.guarded = new LinkedList<>(); + } + this.guarded.add(guarded); + return this; + } + + @Override + public T build() + { + return mapper.apply(new RouteConfig( + order, + exit, + Optional.ofNullable(when).orElse(WHEN_DEFAULT), + with, + Optional.ofNullable(guarded).orElse(GUARDED_DEFAULT))); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryConfig.java index 1121768419..8bf612ad38 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryConfig.java @@ -15,6 +15,8 @@ */ package io.aklivity.zilla.runtime.engine.config; +import static java.util.function.Function.identity; + import java.util.List; public class TelemetryConfig @@ -25,7 +27,12 @@ public class TelemetryConfig public final List metrics; public final List exporters; - public TelemetryConfig( + public static TelemetryConfigBuilder builder() + { + return new TelemetryConfigBuilder<>(identity()); + } + + TelemetryConfig( List attributes, List metrics, List exporters) diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryConfigBuilder.java new file mode 100644 index 0000000000..9b36778e9c --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryConfigBuilder.java @@ -0,0 +1,104 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public final class TelemetryConfigBuilder extends ConfigBuilder> +{ + public static final List ATTRIBUTES_DEFAULT = List.of(); + public static final List METRICS_DEFAULT = List.of(); + public static final List EXPORTERS_DEFAULT = List.of(); + + private final Function mapper; + + private List attributes; + private List metrics; + private List exporters; + + TelemetryConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public AttributeConfigBuilder> attribute() + { + return new AttributeConfigBuilder<>(this::attribute); + } + + public TelemetryConfigBuilder attribute( + AttributeConfig attribute) + { + if (attributes == null) + { + attributes = new LinkedList<>(); + } + attributes.add(attribute); + return this; + } + + public MetricConfigBuilder> metric() + { + return new MetricConfigBuilder<>(this::metric); + } + + public TelemetryConfigBuilder metric( + MetricConfig metric) + { + if (metrics == null) + { + metrics = new LinkedList<>(); + } + metrics.add(metric); + return this; + } + + public ExporterConfigBuilder> exporter() + { + return new ExporterConfigBuilder<>(this::exporter); + } + + public TelemetryConfigBuilder exporter( + ExporterConfig exporter) + { + if (exporters == null) + { + exporters = new LinkedList<>(); + } + exporters.add(exporter); + return this; + } + + @Override + public T build() + { + return mapper.apply(new TelemetryConfig( + Optional.ofNullable(attributes).orElse(ATTRIBUTES_DEFAULT), + Optional.ofNullable(metrics).orElse(METRICS_DEFAULT), + Optional.ofNullable(exporters).orElse(EXPORTERS_DEFAULT))); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryRefConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryRefConfig.java index dde4def647..26bdfa0b1d 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryRefConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryRefConfig.java @@ -15,13 +15,20 @@ */ package io.aklivity.zilla.runtime.engine.config; +import static java.util.function.Function.identity; + import java.util.List; public class TelemetryRefConfig { public final List metricRefs; - public TelemetryRefConfig( + public static TelemetryRefConfigBuilder builder() + { + return new TelemetryRefConfigBuilder<>(identity()); + } + + TelemetryRefConfig( List metricRefs) { this.metricRefs = metricRefs; diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryRefConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryRefConfigBuilder.java new file mode 100644 index 0000000000..3b8503d92f --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/TelemetryRefConfigBuilder.java @@ -0,0 +1,62 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import java.util.LinkedList; +import java.util.List; +import java.util.function.Function; + +public final class TelemetryRefConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private List metrics; + + TelemetryRefConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public MetricRefConfigBuilder> metric() + { + return new MetricRefConfigBuilder<>(this::metric); + } + + public TelemetryRefConfigBuilder metric( + MetricRefConfig metric) + { + if (metrics == null) + { + metrics = new LinkedList<>(); + } + metrics.add(metric); + return this; + } + + @Override + public T build() + { + return mapper.apply(new TelemetryRefConfig(metrics)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/VaultConfig.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/VaultConfig.java index bdbfaacd84..2fcc16c197 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/VaultConfig.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/VaultConfig.java @@ -16,6 +16,7 @@ package io.aklivity.zilla.runtime.engine.config; import static java.util.Objects.requireNonNull; +import static java.util.function.Function.identity; public class VaultConfig { @@ -25,7 +26,12 @@ public class VaultConfig public final String type; public final OptionsConfig options; - public VaultConfig( + public static VaultConfigBuilder builder() + { + return new VaultConfigBuilder<>(identity()); + } + + VaultConfig( String name, String type, OptionsConfig options) diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/VaultConfigBuilder.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/VaultConfigBuilder.java new file mode 100644 index 0000000000..a545cf9038 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/config/VaultConfigBuilder.java @@ -0,0 +1,75 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static java.util.Objects.requireNonNull; + +import java.util.function.Function; + +public final class VaultConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String name; + private String type; + private OptionsConfig options; + + VaultConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public VaultConfigBuilder name( + String name) + { + this.name = name; + return this; + } + + public VaultConfigBuilder type( + String type) + { + this.type = requireNonNull(type); + return this; + } + + public , C>> C options( + Function>, C> options) + { + return options.apply(this::options); + } + + public VaultConfigBuilder options( + OptionsConfig options) + { + this.options = options; + return this; + } + + @Override + public T build() + { + return mapper.apply(new VaultConfig(name, type, options)); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/budget/DefaultBudgetCreditor.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/budget/DefaultBudgetCreditor.java index cc15787d65..07f3a940ad 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/budget/DefaultBudgetCreditor.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/budget/DefaultBudgetCreditor.java @@ -113,6 +113,12 @@ public long acquire( if (budgetIndex != NO_CREDITOR_INDEX) { budgetIndexById.put(budgetId, budgetIndex); + + if (EngineConfiguration.DEBUG_BUDGETS) + { + System.out.format("[%d] acquire creditor budgetId=%d budgetIndex=%d \n", + System.nanoTime(), budgetId, budgetIndex); + } } return budgetIndex; diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/AttributeAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/AttributeAdapter.java index 23580e35a1..1d0b7a4fe8 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/AttributeAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/AttributeAdapter.java @@ -38,12 +38,9 @@ public Map.Entry adaptToJson( public AttributeConfig adaptFromJson( Map.Entry entry) { - return new AttributeConfig(entry.getKey(), asJsonString(entry.getValue())); - } - - private static String asJsonString( - JsonValue value) - { - return ((JsonString) value).getString(); + return AttributeConfig.builder() + .name(entry.getKey()) + .value(JsonString.class.cast(entry.getValue()).getString()) + .build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapter.java index 874fa5cec7..2ea5e22020 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapter.java @@ -15,10 +15,8 @@ */ package io.aklivity.zilla.runtime.engine.internal.config; -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toList; +import static io.aklivity.zilla.runtime.engine.config.BindingConfigBuilder.ROUTES_DEFAULT; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -32,12 +30,10 @@ import org.agrona.collections.MutableInteger; import io.aklivity.zilla.runtime.engine.config.BindingConfig; +import io.aklivity.zilla.runtime.engine.config.BindingConfigBuilder; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; -import io.aklivity.zilla.runtime.engine.config.KindConfig; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -import io.aklivity.zilla.runtime.engine.config.TelemetryRefConfig; public class BindingConfigsAdapter implements JsonbAdapter { @@ -50,8 +46,6 @@ public class BindingConfigsAdapter implements JsonbAdapter ROUTES_DEFAULT = emptyList(); - private final KindAdapter kind; private final RouteAdapter route; private final OptionsAdapter options; @@ -100,9 +94,20 @@ public JsonObject adaptToJson( if (!ROUTES_DEFAULT.equals(binding.routes)) { - JsonArrayBuilder routes = Json.createArrayBuilder(); - binding.routes.forEach(r -> routes.add(route.adaptToJson(r))); - item.add(ROUTES_NAME, routes); + RouteConfig lastRoute = binding.routes.get(binding.routes.size() - 1); + if (lastRoute.exit != null && + lastRoute.guarded.isEmpty() && + lastRoute.when.isEmpty() && + lastRoute.with == null) + { + item.add(EXIT_NAME, lastRoute.exit); + } + else + { + JsonArrayBuilder routes = Json.createArrayBuilder(); + binding.routes.forEach(r -> routes.add(route.adaptToJson(r))); + item.add(ROUTES_NAME, routes); + } } if (binding.telemetryRef != null) @@ -126,49 +131,54 @@ public BindingConfig[] adaptFromJson( for (String name : object.keySet()) { JsonObject item = object.getJsonObject(name); - String type = item.getString(TYPE_NAME); + String type = item.getString(TYPE_NAME); route.adaptType(type); options.adaptType(type); - String vault = item.containsKey(VAULT_NAME) - ? item.getString(VAULT_NAME) - : null; - KindConfig kind = this.kind.adaptFromJson(item.getJsonString(KIND_NAME)); - OptionsConfig opts = item.containsKey(OPTIONS_NAME) ? - options.adaptFromJson(item.getJsonObject(OPTIONS_NAME)) : - null; - MutableInteger order = new MutableInteger(); - List routes = item.containsKey(ROUTES_NAME) - ? item.getJsonArray(ROUTES_NAME) - .stream() - .map(JsonValue::asJsonObject) - .peek(o -> route.adaptFromJsonIndex(order.value++)) - .map(route::adaptFromJson) - .collect(toList()) - : ROUTES_DEFAULT; - - RouteConfig exit = item.containsKey(EXIT_NAME) - ? new RouteConfig(routes.size(), item.getString(EXIT_NAME)) - : null; - - if (exit != null) + BindingConfigBuilder binding = BindingConfig.builder() + .name(name) + .type(type) + .kind(kind.adaptFromJson(item.getJsonString(KIND_NAME))); + + if (item.containsKey(VAULT_NAME)) { - List routesWithExit = new ArrayList<>(); - routesWithExit.addAll(routes); - routesWithExit.add(exit); - routes = routesWithExit; + binding.vault(item.getString(VAULT_NAME)); } - TelemetryRefConfig telemetryRef = item.containsKey(TELEMETRY_NAME) - ? this.telemetryRef.adaptFromJson(item.getJsonObject(TELEMETRY_NAME)) - : null; + if (item.containsKey(OPTIONS_NAME)) + { + binding.options(options.adaptFromJson(item.getJsonObject(OPTIONS_NAME))); + } + + if (item.containsKey(ROUTES_NAME)) + { + MutableInteger order = new MutableInteger(); + + item.getJsonArray(ROUTES_NAME) + .stream() + .map(JsonValue::asJsonObject) + .peek(o -> route.adaptFromJsonIndex(order.value++)) + .map(route::adaptFromJson) + .forEach(binding::route); + } - String entry = item.containsKey(ENTRY_NAME) - ? item.getString(ENTRY_NAME) - : null; + if (item.containsKey(EXIT_NAME)) + { + binding.exit(item.getString(EXIT_NAME)); + } + + if (item.containsKey(TELEMETRY_NAME)) + { + binding.telemetry(telemetryRef.adaptFromJson(item.getJsonObject(TELEMETRY_NAME))); + } + + if (item.containsKey(ENTRY_NAME)) + { + binding.entry(item.getString(ENTRY_NAME)); + } - bindings.add(new BindingConfig(vault, name, type, kind, entry, opts, routes, telemetryRef)); + bindings.add(binding.build()); } return bindings.toArray(BindingConfig[]::new); diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/ExporterAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/ExporterAdapter.java index 4f3f34fd0d..bb1ff43536 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/ExporterAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/ExporterAdapter.java @@ -25,7 +25,6 @@ import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; import io.aklivity.zilla.runtime.engine.config.ExporterConfig; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; public class ExporterAdapter implements JsonbAdapter @@ -68,10 +67,15 @@ public ExporterConfig[] adaptFromJson( for (String name : jsonObject.keySet()) { JsonObject item = jsonObject.getJsonObject(name); + String type = item.getString(TYPE_NAME); options.adaptType(type); - OptionsConfig opts = options.adaptFromJson(item.getJsonObject(OPTIONS_NAME)); - exporters.add(new ExporterConfig(name, type, opts)); + + exporters.add(ExporterConfig.builder() + .name(name) + .type(type) + .options(options.adaptFromJson(item.getJsonObject(OPTIONS_NAME))) + .build()); } return exporters.toArray(ExporterConfig[]::new); } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/GuardAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/GuardAdapter.java index 3b68d3855a..ce682615ca 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/GuardAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/GuardAdapter.java @@ -21,7 +21,7 @@ import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; import io.aklivity.zilla.runtime.engine.config.GuardConfig; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; +import io.aklivity.zilla.runtime.engine.config.GuardConfigBuilder; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; public class GuardAdapter @@ -62,10 +62,15 @@ public GuardConfig adaptFromJson( options.adaptType(type); - OptionsConfig opts = object.containsKey(OPTIONS_NAME) ? - options.adaptFromJson(object.getJsonObject(OPTIONS_NAME)) : - null; + GuardConfigBuilder guard = GuardConfig.builder() + .name(name) + .type(type); - return new GuardConfig(name, type, opts); + if (object.containsKey(OPTIONS_NAME)) + { + guard.options(options.adaptFromJson(object.getJsonObject(OPTIONS_NAME))); + } + + return guard.build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/KindAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/KindAdapter.java index 0b31a9bc91..c49078528f 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/KindAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/KindAdapter.java @@ -24,12 +24,9 @@ public class KindAdapter implements JsonbAdapter { - private final ConfigAdapterContext context; - public KindAdapter( ConfigAdapterContext context) { - this.context = context; } @Override diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricAdapter.java index 8c0e67c907..aae15cdd6a 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricAdapter.java @@ -33,17 +33,15 @@ public JsonValue adaptToJson( @Override public MetricConfig adaptFromJson( - JsonValue jsonValue) + JsonValue value) { - String name = asJsonString(jsonValue); + String name = JsonString.class.cast(value).getString(); String[] parts = name.split("\\."); String group = parts[0]; - return new MetricConfig(group, name); - } - private static String asJsonString( - JsonValue value) - { - return ((JsonString) value).getString(); + return MetricConfig.builder() + .group(group) + .name(name) + .build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricRefAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricRefAdapter.java index 11cb9426b8..340dc253be 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricRefAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/MetricRefAdapter.java @@ -33,14 +33,10 @@ public JsonValue adaptToJson( @Override public MetricRefConfig adaptFromJson( - JsonValue jsonValue) - { - return new MetricRefConfig(asJsonString(jsonValue)); - } - - private static String asJsonString( JsonValue value) { - return ((JsonString) value).getString(); + return MetricRefConfig.builder() + .name(JsonString.class.cast(value).getString()) + .build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceAdapter.java index 658b265384..fa676849df 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceAdapter.java @@ -15,11 +15,13 @@ */ package io.aklivity.zilla.runtime.engine.internal.config; -import static java.util.Collections.emptyList; +import static io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder.BINDINGS_DEFAULT; +import static io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder.GUARDS_DEFAULT; +import static io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder.NAMESPACES_DEFAULT; +import static io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder.TELEMETRY_DEFAULT; +import static io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder.VAULTS_DEFAULT; import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; @@ -30,10 +32,8 @@ import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; -import io.aklivity.zilla.runtime.engine.config.GuardConfig; import io.aklivity.zilla.runtime.engine.config.NamespaceConfig; -import io.aklivity.zilla.runtime.engine.config.TelemetryConfig; -import io.aklivity.zilla.runtime.engine.config.VaultConfig; +import io.aklivity.zilla.runtime.engine.config.NamespaceConfigBuilder; public class NamespaceAdapter implements JsonbAdapter { @@ -44,13 +44,7 @@ public class NamespaceAdapter implements JsonbAdapter NAMESPACES_DEFAULT = emptyList(); - private static final List BINDINGS_DEFAULT = emptyList(); - private static final List GUARDS_DEFAULT = emptyList(); - private static final List VAULTS_DEFAULT = emptyList(); - private static final TelemetryConfig TELEMETRY_DEFAULT = TelemetryConfig.EMPTY; - - private final NamspaceRefAdapter reference; + private final NamspaceRefAdapter namespaceRef; private final TelemetryAdapter telemetry; private final BindingConfigsAdapter binding; private final VaultAdapter vault; @@ -59,7 +53,7 @@ public class NamespaceAdapter implements JsonbAdapter references.add(reference.adaptToJson(r))); + config.references.forEach(r -> references.add(namespaceRef.adaptToJson(r))); object.add(NAMESPACES_NAME, references); } @@ -113,34 +107,43 @@ public JsonObject adaptToJson( public NamespaceConfig adaptFromJson( JsonObject object) { - String name = object.getString(NAME_NAME); - List references = object.containsKey(NAMESPACES_NAME) - ? object.getJsonArray(NAMESPACES_NAME) - .stream().map(JsonValue::asJsonObject) - .map(reference::adaptFromJson) - .collect(Collectors.toList()) - : NAMESPACES_DEFAULT; - TelemetryConfig telemetry0 = object.containsKey(TELEMETRY_NAME) - ? telemetry.adaptFromJson(object.getJsonObject(TELEMETRY_NAME)) - : TELEMETRY_DEFAULT; - List bindings = object.containsKey(BINDINGS_NAME) - ? Arrays.asList(binding.adaptFromJson(object.getJsonObject(BINDINGS_NAME))) - : BINDINGS_DEFAULT; - List guards = object.containsKey(GUARDS_NAME) - ? object.getJsonObject(GUARDS_NAME) - .entrySet() - .stream() - .map(e -> guard.adaptFromJson(e.getKey(), e.getValue().asJsonObject())) - .collect(Collectors.toList()) - : GUARDS_DEFAULT; - List vaults = object.containsKey(VAULTS_NAME) - ? object.getJsonObject(VAULTS_NAME) - .entrySet() - .stream() - .map(e -> vault.adaptFromJson(e.getKey(), e.getValue().asJsonObject())) - .collect(Collectors.toList()) - : VAULTS_DEFAULT; - - return new NamespaceConfig(name, references, telemetry0, bindings, guards, vaults); + NamespaceConfigBuilder namespace = NamespaceConfig.builder(); + + namespace.name(object.getString(NAME_NAME)); + + if (object.containsKey(NAMESPACES_NAME)) + { + object.getJsonArray(NAMESPACES_NAME) + .stream() + .map(JsonValue::asJsonObject) + .map(namespaceRef::adaptFromJson) + .forEach(namespace::namespace); + } + + if (object.containsKey(TELEMETRY_NAME)) + { + namespace.telemetry(telemetry.adaptFromJson(object.getJsonObject(TELEMETRY_NAME))); + } + + if (object.containsKey(BINDINGS_NAME)) + { + namespace.bindings(Arrays.asList(binding.adaptFromJson(object.getJsonObject(BINDINGS_NAME)))); + } + + if (object.containsKey(GUARDS_NAME)) + { + object.getJsonObject(GUARDS_NAME).entrySet().stream() + .map(e -> guard.adaptFromJson(e.getKey(), e.getValue().asJsonObject())) + .forEach(namespace::guard); + } + + if (object.containsKey(VAULTS_NAME)) + { + object.getJsonObject(VAULTS_NAME).entrySet().stream() + .map(e -> vault.adaptFromJson(e.getKey(), e.getValue().asJsonObject())) + .forEach(namespace::vault); + } + + return namespace.build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceRef.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceRef.java deleted file mode 100644 index 7af4999159..0000000000 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceRef.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.engine.internal.config; - -import java.util.Map; - -public class NamespaceRef -{ - public final String name; - public final Map links; - - public NamespaceRef( - String name, - Map links) - { - this.name = name; - this.links = links; - } -} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamspaceRefAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamspaceRefAdapter.java index 62728ea756..e928964730 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamspaceRefAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/NamspaceRefAdapter.java @@ -15,38 +15,31 @@ */ package io.aklivity.zilla.runtime.engine.internal.config; -import static java.util.Collections.emptyMap; -import static java.util.stream.Collectors.toMap; - -import java.util.Map; +import static io.aklivity.zilla.runtime.engine.config.NamespaceRefConfigBuilder.LINKS_DEFAULT; import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; import jakarta.json.JsonString; -import jakarta.json.JsonValue; import jakarta.json.bind.adapter.JsonbAdapter; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; +import io.aklivity.zilla.runtime.engine.config.NamespaceRefConfig; +import io.aklivity.zilla.runtime.engine.config.NamespaceRefConfigBuilder; -public class NamspaceRefAdapter implements JsonbAdapter +public class NamspaceRefAdapter implements JsonbAdapter { private static final String NAME_NAME = "name"; private static final String LINKS_NAME = "links"; - private static final Map LINKS_DEFAULT = emptyMap(); - - private final ConfigAdapterContext context; - public NamspaceRefAdapter( ConfigAdapterContext context) { - this.context = context; } @Override public JsonObject adaptToJson( - NamespaceRef ref) + NamespaceRefConfig ref) { JsonObjectBuilder object = Json.createObjectBuilder(); @@ -63,23 +56,21 @@ public JsonObject adaptToJson( } @Override - public NamespaceRef adaptFromJson( + public NamespaceRefConfig adaptFromJson( JsonObject object) { - String name = object.getString(NAME_NAME); - Map links = object.containsKey(LINKS_NAME) - ? object.getJsonObject(LINKS_NAME) - .entrySet() - .stream() - .collect(toMap(Map.Entry::getKey, e -> asJsonString(e.getValue()))) - : LINKS_DEFAULT; + NamespaceRefConfigBuilder namespace = NamespaceRefConfig.builder(); - return new NamespaceRef(name, links); - } + namespace.name(object.getString(NAME_NAME)); - private static String asJsonString( - JsonValue value) - { - return ((JsonString) value).getString(); + if (object.containsKey(LINKS_NAME)) + { + object.getJsonObject(LINKS_NAME) + .entrySet() + .stream() + .forEach(e -> namespace.link(e.getKey(), JsonString.class.cast(e.getValue()).getString())); + } + + return namespace.build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/RouteAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/RouteAdapter.java index aa09292b0c..bfa617fa44 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/RouteAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/RouteAdapter.java @@ -15,12 +15,8 @@ */ package io.aklivity.zilla.runtime.engine.internal.config; -import static io.aklivity.zilla.runtime.engine.config.RouteConfig.GUARDED_DEFAULT; -import static io.aklivity.zilla.runtime.engine.config.RouteConfig.WHEN_DEFAULT; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; +import static io.aklivity.zilla.runtime.engine.config.RouteConfigBuilder.GUARDED_DEFAULT; +import static io.aklivity.zilla.runtime.engine.config.RouteConfigBuilder.WHEN_DEFAULT; import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; @@ -30,11 +26,11 @@ import jakarta.json.JsonValue; import jakarta.json.bind.adapter.JsonbAdapter; -import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; import io.aklivity.zilla.runtime.engine.config.GuardedConfig; +import io.aklivity.zilla.runtime.engine.config.GuardedConfigBuilder; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -import io.aklivity.zilla.runtime.engine.config.WithConfig; +import io.aklivity.zilla.runtime.engine.config.RouteConfigBuilder; public class RouteAdapter implements JsonbAdapter { @@ -43,15 +39,14 @@ public class RouteAdapter implements JsonbAdapter private static final String WITH_NAME = "with"; private static final String GUARDED_NAME = "guarded"; - private int index; private final ConditionAdapter condition; private final WithAdapter with; - private ConfigAdapterContext context; + + private int index; public RouteAdapter( ConfigAdapterContext context) { - this.context = context; condition = new ConditionAdapter(); with = new WithAdapter(); } @@ -114,37 +109,46 @@ public JsonObject adaptToJson( public RouteConfig adaptFromJson( JsonObject object) { - String newExit = object.containsKey(EXIT_NAME) - ? object.getString(EXIT_NAME) - : null; - List newWhen = object.containsKey(WHEN_NAME) - ? object.getJsonArray(WHEN_NAME) - .stream().map(JsonValue::asJsonObject) - .map(condition::adaptFromJson) - .collect(Collectors.toList()) - : WHEN_DEFAULT; - WithConfig newWith = object.containsKey(WITH_NAME) - ? with.adaptFromJson(object.getJsonObject(WITH_NAME)) - : null; - - List newGuarded = GUARDED_DEFAULT; - if (object.containsKey(GUARDED_NAME)) + RouteConfigBuilder route = RouteConfig.builder() + .order(index); + + if (object.containsKey(EXIT_NAME)) + { + route.exit(object.getString(EXIT_NAME)); + } + + if (object.containsKey(WHEN_NAME)) + { + object.getJsonArray(WHEN_NAME) + .stream() + .map(JsonValue::asJsonObject) + .map(condition::adaptFromJson) + .forEach(route::when); + } + + if (object.containsKey(WITH_NAME)) { - newGuarded = new ArrayList<>(); + route.with(with.adaptFromJson(object.getJsonObject(WITH_NAME))); + } + if (object.containsKey(GUARDED_NAME)) + { JsonObject guarded = object.getJsonObject(GUARDED_NAME); for (String name : guarded.keySet()) { - List roles = guarded.getJsonArray(name) + GuardedConfigBuilder guardedBy = route.guarded() + .name(name); + + guarded.getJsonArray(name) .stream() .map(JsonString.class::cast) .map(JsonString::getString) - .collect(Collectors.toList()); + .forEach(guardedBy::role); - newGuarded.add(new GuardedConfig(name, roles)); + guardedBy.build(); } } - return new RouteConfig(index, newExit, newWhen, newWith, newGuarded); + return route.build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryAdapter.java index 2374b6493c..eb0f448b71 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryAdapter.java @@ -16,9 +16,7 @@ package io.aklivity.zilla.runtime.engine.internal.config; import java.util.Arrays; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; @@ -30,8 +28,8 @@ import io.aklivity.zilla.runtime.engine.config.AttributeConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; import io.aklivity.zilla.runtime.engine.config.ExporterConfig; -import io.aklivity.zilla.runtime.engine.config.MetricConfig; import io.aklivity.zilla.runtime.engine.config.TelemetryConfig; +import io.aklivity.zilla.runtime.engine.config.TelemetryConfigBuilder; public class TelemetryAdapter implements JsonbAdapter { @@ -77,23 +75,30 @@ public JsonObject adaptToJson( @Override public TelemetryConfig adaptFromJson( - JsonObject jsonObject) + JsonObject object) { - List attributes = jsonObject.containsKey(ATTRIBUTES_NAME) - ? jsonObject.getJsonObject(ATTRIBUTES_NAME).entrySet().stream() - .map(attribute::adaptFromJson) - .collect(Collectors.toList()) - : List.of(); - List metrics = jsonObject.containsKey(METRICS_NAME) - ? jsonObject.getJsonArray(METRICS_NAME).stream() - .map(metric::adaptFromJson) - .collect(Collectors.toList()) - : List.of(); - List exporters = jsonObject.containsKey(EXPORTERS_NAME) - ? Arrays.stream(exporter.adaptFromJson(jsonObject.getJsonObject(EXPORTERS_NAME))) - .collect(Collectors.toList()) - : List.of(); - - return new TelemetryConfig(attributes, metrics, exporters); + TelemetryConfigBuilder telemetry = TelemetryConfig.builder(); + + if (object.containsKey(ATTRIBUTES_NAME)) + { + object.getJsonObject(ATTRIBUTES_NAME).entrySet().stream() + .map(attribute::adaptFromJson) + .forEach(telemetry::attribute); + } + + if (object.containsKey(METRICS_NAME)) + { + object.getJsonArray(METRICS_NAME).stream() + .map(metric::adaptFromJson) + .forEach(telemetry::metric); + } + + if (object.containsKey(EXPORTERS_NAME)) + { + Arrays.stream(exporter.adaptFromJson(object.getJsonObject(EXPORTERS_NAME))) + .forEach(telemetry::exporter); + } + + return telemetry.build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryRefAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryRefAdapter.java index 3ef1114f1b..d7b0dd4095 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryRefAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryRefAdapter.java @@ -15,19 +15,14 @@ */ package io.aklivity.zilla.runtime.engine.internal.config; -import java.util.List; -import java.util.stream.Collectors; - import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; -import jakarta.json.JsonString; -import jakarta.json.JsonValue; import jakarta.json.bind.adapter.JsonbAdapter; -import io.aklivity.zilla.runtime.engine.config.MetricRefConfig; import io.aklivity.zilla.runtime.engine.config.TelemetryRefConfig; +import io.aklivity.zilla.runtime.engine.config.TelemetryRefConfigBuilder; public class TelemetryRefAdapter implements JsonbAdapter { @@ -53,19 +48,17 @@ public JsonObject adaptToJson( @Override public TelemetryRefConfig adaptFromJson( - JsonObject jsonObject) + JsonObject object) { - List metricRefs = jsonObject.containsKey(METRICS_NAME) - ? jsonObject.getJsonArray(METRICS_NAME).stream() - .map(metricRef::adaptFromJson) - .collect(Collectors.toList()) - : List.of(); - return new TelemetryRefConfig(metricRefs); - } + TelemetryRefConfigBuilder telemetry = TelemetryRefConfig.builder(); - private static String asJsonString( - JsonValue value) - { - return ((JsonString) value).getString(); + if (object.containsKey(METRICS_NAME)) + { + object.getJsonArray(METRICS_NAME).stream() + .map(metricRef::adaptFromJson) + .forEach(telemetry::metric); + } + + return telemetry.build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/VaultAdapter.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/VaultAdapter.java index 3045263791..0bc03d7114 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/VaultAdapter.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/VaultAdapter.java @@ -20,9 +20,9 @@ import jakarta.json.JsonObjectBuilder; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; import io.aklivity.zilla.runtime.engine.config.VaultConfig; +import io.aklivity.zilla.runtime.engine.config.VaultConfigBuilder; public class VaultAdapter { @@ -59,13 +59,17 @@ public VaultConfig adaptFromJson( JsonObject object) { String type = object.getString(TYPE_NAME); - options.adaptType(type); - OptionsConfig opts = object.containsKey(OPTIONS_NAME) ? - options.adaptFromJson(object.getJsonObject(OPTIONS_NAME)) : - null; + VaultConfigBuilder vault = VaultConfig.builder() + .name(name) + .type(type); + + if (object.containsKey(OPTIONS_NAME)) + { + vault.options(options.adaptFromJson(object.getJsonObject(OPTIONS_NAME))); + } - return new VaultConfig(name, type, opts); + return vault.build(); } } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/json/SchemaDecorator.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/schema/SchemaDecorator.java similarity index 98% rename from runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/json/SchemaDecorator.java rename to runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/schema/SchemaDecorator.java index 4328d7a9cf..820de7d69a 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/json/SchemaDecorator.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/schema/SchemaDecorator.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.engine.internal.registry.json; +package io.aklivity.zilla.runtime.engine.internal.config.schema; import java.net.URI; import java.util.stream.Stream; diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/json/UniquePropertyKeysSchema.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/schema/UniquePropertyKeysSchema.java similarity index 98% rename from runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/json/UniquePropertyKeysSchema.java rename to runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/schema/UniquePropertyKeysSchema.java index 783ff8156b..2be041d77b 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/json/UniquePropertyKeysSchema.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/config/schema/UniquePropertyKeysSchema.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.aklivity.zilla.runtime.engine.internal.registry.json; +package io.aklivity.zilla.runtime.engine.internal.config.schema; import java.util.Deque; import java.util.HashSet; diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/ConfigurationManager.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/ConfigurationManager.java index 81d79c0f14..b1214fe167 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/ConfigurationManager.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/ConfigurationManager.java @@ -15,16 +15,11 @@ */ package io.aklivity.zilla.runtime.engine.internal.registry; -import static jakarta.json.stream.JsonGenerator.PRETTY_PRINTING; -import static java.util.Collections.singletonMap; - -import java.io.InputStream; import java.io.StringReader; -import java.io.StringWriter; import java.net.URL; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -37,25 +32,10 @@ import java.util.function.ToIntFunction; import java.util.regex.Pattern; -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import jakarta.json.JsonPatch; -import jakarta.json.JsonReader; -import jakarta.json.bind.Jsonb; -import jakarta.json.bind.JsonbBuilder; -import jakarta.json.bind.JsonbConfig; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonParser; - -import org.leadpony.justify.api.JsonSchema; -import org.leadpony.justify.api.JsonSchemaReader; -import org.leadpony.justify.api.JsonValidationService; -import org.leadpony.justify.api.ProblemHandler; - -import io.aklivity.zilla.runtime.engine.Engine; import io.aklivity.zilla.runtime.engine.EngineConfiguration; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; +import io.aklivity.zilla.runtime.engine.config.ConfigReader; import io.aklivity.zilla.runtime.engine.config.GuardConfig; import io.aklivity.zilla.runtime.engine.config.GuardedConfig; import io.aklivity.zilla.runtime.engine.config.KindConfig; @@ -69,8 +49,6 @@ import io.aklivity.zilla.runtime.engine.ext.EngineExtSpi; import io.aklivity.zilla.runtime.engine.guard.Guard; import io.aklivity.zilla.runtime.engine.internal.Tuning; -import io.aklivity.zilla.runtime.engine.internal.config.NamespaceAdapter; -import io.aklivity.zilla.runtime.engine.internal.registry.json.UniquePropertyKeysSchema; import io.aklivity.zilla.runtime.engine.internal.stream.NamespacedId; public class ConfigurationManager @@ -134,71 +112,16 @@ public NamespaceConfig parse( configText = expressions.resolve(configText); } - List errors = new LinkedList<>(); - parse: try { - //TODO: detect configURLs and call handleConfigURL - InputStream schemaInput = Engine.class.getResourceAsStream("internal/schema/engine.schema.json"); - - JsonProvider schemaProvider = JsonProvider.provider(); - JsonReader schemaReader = schemaProvider.createReader(schemaInput); - JsonObject schemaObject = schemaReader.readObject(); - - for (URL schemaType : schemaTypes) - { - InputStream schemaPatchInput = schemaType.openStream(); - JsonReader schemaPatchReader = schemaProvider.createReader(schemaPatchInput); - JsonArray schemaPatchArray = schemaPatchReader.readArray(); - JsonPatch schemaPatch = schemaProvider.createPatch(schemaPatchArray); - - schemaObject = schemaPatch.apply(schemaObject); - } - - if (config.verboseSchema()) - { - final StringWriter out = new StringWriter(); - schemaProvider.createGeneratorFactory(singletonMap(PRETTY_PRINTING, true)) - .createGenerator(out) - .write(schemaObject) - .close(); - - final String schemaText = out.getBuffer().toString(); - logger.accept(schemaText); - } - - JsonParser schemaParser = schemaProvider.createParserFactory(null) - .createParser(new StringReader(schemaObject.toString())); - - JsonValidationService service = JsonValidationService.newInstance(); - ProblemHandler handler = service.createProblemPrinter(errors::add); - JsonSchemaReader reader = service.createSchemaReader(schemaParser); - JsonSchema schema = new UniquePropertyKeysSchema(reader.read()); - - JsonProvider provider = service.createJsonProvider(schema, parser -> handler); - provider.createReader(new StringReader(configText)).read(); - - if (!errors.isEmpty()) - { - break parse; - } - final Function namespaceReadURL = l -> readURL.apply(configURL, l); - JsonbConfig config = new JsonbConfig() - .withAdapters(new NamespaceAdapter(new NamespaceConfigAdapterContext(namespaceReadURL))); - Jsonb jsonb = JsonbBuilder.newBuilder() - .withProvider(provider) - .withConfig(config) - .build(); - - namespace = jsonb.fromJson(configText, NamespaceConfig.class); - - if (!errors.isEmpty()) - { - break parse; - } + ConfigReader reader = new ConfigReader( + new NamespaceConfigAdapterContext(namespaceReadURL), + schemaTypes, + config.verboseSchema() ? logger : null); + namespace = reader.read(new StringReader(configText)); namespace.id = supplyId.applyAsInt(namespace.name); namespace.readURL = namespaceReadURL; @@ -281,12 +204,11 @@ public NamespaceConfig parse( catch (Throwable ex) { logError(ex.getMessage()); + Arrays.stream(ex.getSuppressed()) + .map(Throwable::getMessage) + .forEach(logger); } - if (!errors.isEmpty()) - { - errors.forEach(this::logError); - } return namespace; } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/DispatchAgent.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/DispatchAgent.java index 3dd2a7a62a..5c2fa9357e 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/DispatchAgent.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/DispatchAgent.java @@ -238,21 +238,21 @@ public DispatchAgent( this.countersLayout = new ScalarsLayout.Builder() .path(config.directory().resolve(String.format("metrics/counters%d", index))) - .capacity(config.counterBufferCapacity()) + .capacity(config.countersBufferCapacity()) .readonly(readonly) .label("counters") .build(); this.gaugesLayout = new ScalarsLayout.Builder() .path(config.directory().resolve(String.format("metrics/gauges%d", index))) - .capacity(config.counterBufferCapacity()) + .capacity(config.countersBufferCapacity()) .readonly(readonly) .label("gauges") .build(); this.histogramsLayout = new HistogramsLayout.Builder() .path(config.directory().resolve(String.format("metrics/histograms%d", index))) - .capacity(config.counterBufferCapacity()) + .capacity(config.countersBufferCapacity()) .readonly(readonly) .build(); diff --git a/runtime/engine/src/main/moditect/module-info.java b/runtime/engine/src/main/moditect/module-info.java index a3f60b0c5a..d3db1ae724 100644 --- a/runtime/engine/src/main/moditect/module-info.java +++ b/runtime/engine/src/main/moditect/module-info.java @@ -38,6 +38,8 @@ requires transitive jakarta.json.bind; requires transitive org.agrona.core; requires org.leadpony.justify; + requires com.fasterxml.jackson.dataformat.yaml; + requires com.fasterxml.jackson.databind; requires jdk.unsupported; requires java.net.http; diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/config/ConfigWriterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/config/ConfigWriterTest.java new file mode 100644 index 0000000000..71498f7cc2 --- /dev/null +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/config/ConfigWriterTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.config; + +import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; +import static java.util.function.Function.identity; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; + +import jakarta.json.Json; +import jakarta.json.JsonPatch; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.mockito.quality.Strictness; + +import io.aklivity.zilla.runtime.engine.internal.config.ConditionConfigAdapterTest.TestConditionConfig; +import io.aklivity.zilla.runtime.engine.test.internal.binding.config.TestBindingOptionsConfig; + +public class ConfigWriterTest +{ + @Rule + public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); + + @Mock + private ConfigAdapterContext context; + + private ConfigWriter yaml; + + @Before + public void initYaml() + { + yaml = new ConfigWriter(context); + } + + @Test + public void shouldWriteNamespace() + { + // GIVEN + NamespaceConfig config = NamespaceConfig.builder() + .name("test") + .binding() + .inject(identity()) + .name("test0") + .type("test") + .kind(SERVER) + .options(TestBindingOptionsConfig::builder) + .inject(identity()) + .mode("test") + .build() + .route() + .inject(identity()) + .when(TestConditionConfig::builder) + .inject(identity()) + .match("test") + .build() + .exit("exit0") + .build() + .build() + .build(); + + // WHEN + String text = yaml.write(config); + + // THEN + assertThat(text, not(nullValue())); + assertThat(text, equalTo(String.join("\n", + new String[] { + "name: test", + "bindings:", + " test0:", + " type: test", + " kind: server", + " options:", + " mode: test", + " routes:", + " - exit: exit0", + " when:", + " - match: test", + "" + }))); + } + + @Test + public void shouldPatchAndWriteNamespace() + { + // GIVEN + NamespaceConfig config = NamespaceConfig.builder() + .name("test") + .binding() + .name("test0") + .type("test") + .kind(SERVER) + .options(TestBindingOptionsConfig::builder) + .mode("test") + .build() + .route() + .when(TestConditionConfig::builder) + .match("test") + .build() + .exit("exit0") + .build() + .build() + .build(); + JsonPatch patch = Json.createPatchBuilder() + .replace("/bindings/test0/type", "newType") + .build(); + + // WHEN + String text = yaml.write(config, patch); + + // THEN + assertThat(text, not(nullValue())); + assertThat(text, equalTo(String.join("\n", + new String[] { + "name: test", + "bindings:", + " test0:", + " type: newType", + " kind: server", + " options:", + " mode: test", + " routes:", + " - exit: exit0", + " when:", + " - match: test", + "" + }))); + } +} diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineIT.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineIT.java index 6f8b6d34d0..158e3ec490 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineIT.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineIT.java @@ -18,6 +18,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.rules.RuleChain.outerRule; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.DisableOnDebug; @@ -39,9 +40,7 @@ public class EngineIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(4096) + .countersBufferCapacity(4096) .configurationRoot("io/aklivity/zilla/specs/engine/config") .external("app0") .clean(); @@ -119,6 +118,7 @@ public void shouldReceiveClientSentWriteClose() throws Exception k3po.finish(); } + @Ignore("GitHub Actions") @Test @Configuration("server.yaml") @Specification({ diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureFileIT.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureFileIT.java index 3aaa3ec44b..e57e33072d 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureFileIT.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureFileIT.java @@ -54,9 +54,7 @@ public class ReconfigureFileIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/runtime/engine/internal") .external("app0") diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureHttpIT.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureHttpIT.java index 16cd085090..936c5bb85c 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureHttpIT.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/ReconfigureHttpIT.java @@ -48,9 +48,7 @@ public class ReconfigureHttpIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configure(ENGINE_DRAIN_ON_CLOSE, false) .configurationRoot("io/aklivity/zilla/runtime/engine/internal") .external("app0") diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapterTest.java index e416967e6a..3811b35d3f 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapterTest.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/BindingConfigsAdapterTest.java @@ -17,8 +17,7 @@ import static io.aklivity.zilla.runtime.engine.config.KindConfig.REMOTE_SERVER; import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.emptyCollectionOf; @@ -28,8 +27,6 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; -import java.util.List; - import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; @@ -44,9 +41,7 @@ import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; -import io.aklivity.zilla.runtime.engine.config.MetricRefConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; -import io.aklivity.zilla.runtime.engine.config.TelemetryRefConfig; import io.aklivity.zilla.runtime.engine.test.internal.binding.config.TestBindingOptionsConfig; public class BindingConfigsAdapterTest @@ -90,7 +85,15 @@ public void shouldReadBinding() @Test public void shouldWriteBinding() { - BindingConfig[] bindings = { new BindingConfig(null, "test", "test", SERVER, null, null, emptyList(), null) }; + BindingConfig[] bindings = + { + BindingConfig.builder() + .inject(identity()) + .name("test") + .type("test") + .kind(SERVER) + .build() + }; String text = jsonb.toJson(bindings); @@ -126,7 +129,16 @@ public void shouldReadBindingWithVault() @Test public void shouldWriteBindingWithVault() { - BindingConfig[] bindings = { new BindingConfig("test", "test", "test", SERVER, null, null, emptyList(), null) }; + BindingConfig[] bindings = + { + BindingConfig.builder() + .inject(identity()) + .vault("test") + .name("test") + .type("test") + .kind(SERVER) + .build() + }; String text = jsonb.toJson(bindings); @@ -163,7 +175,17 @@ public void shouldReadBindingWithOptions() public void shouldWriteBindingWithOptions() { BindingConfig[] bindings = - { new BindingConfig(null, "test", "test", SERVER, null, new TestBindingOptionsConfig("test"), emptyList(), null) }; + { + BindingConfig.builder() + .name("test") + .type("test") + .kind(SERVER) + .options(TestBindingOptionsConfig::builder) + .inject(identity()) + .mode("test") + .build() + .build() + }; String text = jsonb.toJson(bindings); @@ -199,16 +221,50 @@ public void shouldReadBindingWithRoute() assertThat(bindings[0].routes.get(0).when, empty()); } + @Test + public void shouldWriteBindingWithExit() + { + BindingConfig[] bindings = + { + BindingConfig.builder() + .inject(identity()) + .name("test") + .type("test") + .kind(SERVER) + .exit("test") + .build() + }; + + String text = jsonb.toJson(bindings); + + assertThat(text, not(nullValue())); + assertThat(text, equalTo("{\"test\":{\"type\":\"test\",\"kind\":\"server\",\"exit\":\"test\"}}")); + } @Test public void shouldWriteBindingWithRoute() { BindingConfig[] bindings = - { new BindingConfig(null, "test", "test", SERVER, null, null, singletonList(new RouteConfig("test")), null) }; + { + BindingConfig.builder() + .name("test") + .type("test") + .kind(SERVER) + .route() + .exit("test") + .guarded() + .inject(identity()) + .name("test0") + .role("read") + .build() + .build() + .build() + }; String text = jsonb.toJson(bindings); assertThat(text, not(nullValue())); - assertThat(text, equalTo("{\"test\":{\"type\":\"test\",\"kind\":\"server\",\"routes\":[{\"exit\":\"test\"}]}}")); + assertThat(text, equalTo("{\"test\":{\"type\":\"test\",\"kind\":\"server\"," + + "\"routes\":[{\"exit\":\"test\",\"guarded\":{\"test0\":[\"read\"]}}]}}")); } @Test @@ -272,9 +328,19 @@ public void shouldReadBindingWithRemoteServerKind() @Test public void shouldWriteBindingWithTelemetry() { - TelemetryRefConfig telemetry = new TelemetryRefConfig(List.of(new MetricRefConfig("test.counter"))); BindingConfig[] bindings = - { new BindingConfig(null, "test", "test", SERVER, null, null, List.of(), telemetry) }; + { + BindingConfig.builder() + .name("test") + .type("test") + .kind(SERVER) + .telemetry() + .metric() + .name("test.counter") + .build() + .build() + .build() + }; String text = jsonb.toJson(bindings); @@ -287,14 +353,22 @@ public void shouldWriteBindingWithTelemetry() public void shouldWriteBindingWithRemoteServerKind() { BindingConfig[] bindings = - { new BindingConfig(null, "test", "test", REMOTE_SERVER, "test_entry", - null, singletonList(new RouteConfig("test")), null) }; + { + BindingConfig.builder() + .name("test") + .type("test") + .kind(REMOTE_SERVER) + .entry("test_entry") + .route() + .exit("test") + .build() + .build() + }; String text = jsonb.toJson(bindings); assertThat(text, not(nullValue())); assertThat(text, equalTo("{\"test\":{\"type\":\"test\",\"kind\":\"remote_server\"," + - "\"entry\":\"test_entry\",\"routes\":[{\"exit\":\"test\"}]}}")); - + "\"entry\":\"test_entry\",\"exit\":\"test\"}}")); } } diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/ConditionConfigAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/ConditionConfigAdapterTest.java index 39b9db3b17..5f525cd250 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/ConditionConfigAdapterTest.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/ConditionConfigAdapterTest.java @@ -20,6 +20,8 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import java.util.function.Function; + import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; @@ -32,6 +34,7 @@ import io.aklivity.zilla.runtime.engine.config.ConditionConfig; import io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; public class ConditionConfigAdapterTest { @@ -103,13 +106,57 @@ public static final class TestConditionConfig extends ConditionConfig { public final String match; - public TestConditionConfig( + public static TestConditionConfigBuilder builder() + { + return new TestConditionConfigBuilder<>(TestConditionConfig.class::cast); + } + + public static TestConditionConfigBuilder builder( + Function mapper) + { + return new TestConditionConfigBuilder<>(mapper); + } + + TestConditionConfig( String match) { this.match = match; } } + public static final class TestConditionConfigBuilder extends ConfigBuilder> + { + private final Function mapper; + + private String match; + + TestConditionConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TestConditionConfigBuilder match( + String match) + { + this.match = match; + return this; + } + + @Override + public T build() + { + return mapper.apply(new TestConditionConfig(match)); + } + } + public static final class TestConditionConfigAdapter implements ConditionConfigAdapterSpi { private static final String MATCH_NAME = "match"; diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceConfigAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceConfigAdapterTest.java index 989d3f225e..cf92c2f525 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceConfigAdapterTest.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceConfigAdapterTest.java @@ -16,9 +16,8 @@ package io.aklivity.zilla.runtime.engine.internal.config; import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; -import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyCollectionOf; import static org.hamcrest.Matchers.equalTo; @@ -26,7 +25,7 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; -import java.util.List; +import java.time.Duration; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; @@ -40,16 +39,14 @@ import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; -import io.aklivity.zilla.runtime.engine.config.AttributeConfig; import io.aklivity.zilla.runtime.engine.config.BindingConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; -import io.aklivity.zilla.runtime.engine.config.ExporterConfig; -import io.aklivity.zilla.runtime.engine.config.GuardConfig; -import io.aklivity.zilla.runtime.engine.config.MetricConfig; import io.aklivity.zilla.runtime.engine.config.NamespaceConfig; -import io.aklivity.zilla.runtime.engine.config.TelemetryConfig; +import io.aklivity.zilla.runtime.engine.config.NamespaceRefConfig; import io.aklivity.zilla.runtime.engine.config.VaultConfig; import io.aklivity.zilla.runtime.engine.test.internal.exporter.config.TestExporterOptionsConfig; +import io.aklivity.zilla.runtime.engine.test.internal.guard.config.TestGuardOptionsConfig; +import io.aklivity.zilla.runtime.engine.test.internal.vault.config.TestVaultOptionsConfig; public class NamespaceConfigAdapterTest { @@ -93,13 +90,15 @@ public void shouldReadNamespace() assertThat(config.name, equalTo("test")); assertThat(config.bindings, emptyCollectionOf(BindingConfig.class)); assertThat(config.vaults, emptyCollectionOf(VaultConfig.class)); - assertThat(config.references, emptyCollectionOf(NamespaceRef.class)); + assertThat(config.references, emptyCollectionOf(NamespaceRefConfig.class)); } @Test public void shouldWriteNamespace() { - NamespaceConfig config = new NamespaceConfig("test", emptyList(), null, emptyList(), emptyList(), emptyList()); + NamespaceConfig config = NamespaceConfig.builder() + .name("test") + .build(); String text = jsonb.toJson(config); @@ -135,17 +134,23 @@ public void shouldReadNamespaceWithBinding() assertThat(config.bindings.get(0).type, equalTo("test")); assertThat(config.bindings.get(0).kind, equalTo(SERVER)); assertThat(config.vaults, emptyCollectionOf(VaultConfig.class)); - assertThat(config.references, emptyCollectionOf(NamespaceRef.class)); + assertThat(config.references, emptyCollectionOf(NamespaceRefConfig.class)); } @Test public void shouldWriteNamespaceWithBinding() { - BindingConfig binding = new BindingConfig(null, "test", "test", SERVER, null, null, emptyList(), null); - NamespaceConfig namespace = new NamespaceConfig("test", emptyList(), null, - singletonList(binding), emptyList(), emptyList()); + NamespaceConfig config = NamespaceConfig.builder() + .inject(identity()) + .name("test") + .binding() + .name("test") + .type("test") + .kind(SERVER) + .build() + .build(); - String text = jsonb.toJson(namespace); + String text = jsonb.toJson(config); assertThat(text, not(nullValue())); assertThat(text, equalTo("{\"name\":\"test\",\"bindings\":{\"test\":{\"type\":\"test\",\"kind\":\"server\"}}}")); @@ -181,13 +186,24 @@ public void shouldReadNamespaceWithGuard() @Test public void shouldWriteNamespaceWithGuard() { - GuardConfig guard = new GuardConfig("default", "test", null); - NamespaceConfig config = new NamespaceConfig("test", emptyList(), null, emptyList(), singletonList(guard), emptyList()); + NamespaceConfig config = NamespaceConfig.builder() + .inject(identity()) + .name("test") + .guard() + .name("default") + .type("test") + .options(TestGuardOptionsConfig::builder) + .credentials("token") + .lifetime(Duration.ofSeconds(10)) + .build() + .build() + .build(); String text = jsonb.toJson(config); assertThat(text, not(nullValue())); - assertThat(text, equalTo("{\"name\":\"test\",\"guards\":{\"default\":{\"type\":\"test\"}}}")); + assertThat(text, equalTo("{\"name\":\"test\",\"guards\":{\"default\":{\"type\":\"test\"," + + "\"options\":{\"credentials\":\"token\",\"lifetime\":\"PT10S\"}}}}")); } @Test @@ -220,13 +236,23 @@ public void shouldReadNamespaceWithVault() @Test public void shouldWriteNamespaceWithVault() { - VaultConfig vault = new VaultConfig("default", "test", null); - NamespaceConfig config = new NamespaceConfig("test", emptyList(), null, emptyList(), emptyList(), singletonList(vault)); + NamespaceConfig config = NamespaceConfig.builder() + .inject(identity()) + .name("test") + .vault() + .name("default") + .type("test") + .options(TestVaultOptionsConfig::builder) + .mode("test") + .build() + .build() + .build(); String text = jsonb.toJson(config); assertThat(text, not(nullValue())); - assertThat(text, equalTo("{\"name\":\"test\",\"vaults\":{\"default\":{\"type\":\"test\"}}}")); + assertThat(text, equalTo("{\"name\":\"test\",\"vaults\":{\"default\":{\"type\":\"test\"," + + "\"options\":{\"mode\":\"test\"}}}}")); } @Test @@ -258,12 +284,27 @@ public void shouldReadNamespaceWithTelemetry() @Test public void shouldWriteNamespaceWithTelemetry() { - TelemetryConfig telemetry = new TelemetryConfig( - List.of(new AttributeConfig("test.attribute", "example")), - List.of(new MetricConfig("test", "test.counter")), - List.of(new ExporterConfig("test0", "test", new TestExporterOptionsConfig("test42"))) - ); - NamespaceConfig config = new NamespaceConfig("test", emptyList(), telemetry, emptyList(), emptyList(), emptyList()); + NamespaceConfig config = NamespaceConfig.builder() + .inject(identity()) + .name("test") + .telemetry() + .attribute() + .name("test.attribute") + .value("example") + .build() + .metric() + .group("test") + .name("test.counter") + .build() + .exporter() + .name("test0") + .type("test") + .options(TestExporterOptionsConfig::builder) + .mode("test42") + .build() + .build() + .build() + .build(); String text = jsonb.toJson(config); @@ -303,9 +344,13 @@ public void shouldReadNamespaceWithReference() @Test public void shouldWriteNamespaceWithReference() { - NamespaceRef reference = new NamespaceRef("test", emptyMap()); - NamespaceConfig config = new NamespaceConfig("test", singletonList(reference), null, - emptyList(), emptyList(), emptyList()); + NamespaceConfig config = NamespaceConfig.builder() + .inject(identity()) + .name("test") + .namespace() + .name("test") + .build() + .build(); String text = jsonb.toJson(config); diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceRefConfigAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceRefConfigAdapterTest.java new file mode 100644 index 0000000000..7d288844bd --- /dev/null +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/NamespaceRefConfigAdapterTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.internal.config; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static java.util.function.Function.identity; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; + +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.mockito.quality.Strictness; + +import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; +import io.aklivity.zilla.runtime.engine.config.NamespaceRefConfig; + +public class NamespaceRefConfigAdapterTest +{ + @Rule + public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); + + @Mock + private ConfigAdapterContext context; + private Jsonb jsonb; + + @Before + public void initJson() + { + JsonbConfig config = new JsonbConfig() + .withAdapters(new NamspaceRefAdapter(context)); + jsonb = JsonbBuilder.create(config); + } + + @Test + public void shouldReadReference() + { + String text = + "{" + + "\"name\": \"test\"" + + "}"; + + NamespaceRefConfig ref = jsonb.fromJson(text, NamespaceRefConfig.class); + + assertThat(ref, not(nullValue())); + assertThat(ref.name, equalTo("test")); + assertThat(ref.links, equalTo(emptyMap())); + } + + + @Test + public void shouldWriteReference() + { + NamespaceRefConfig reference = NamespaceRefConfig.builder() + .name("test") + .build(); + + String text = jsonb.toJson(reference); + + assertThat(text, not(nullValue())); + assertThat(text, equalTo("{\"name\":\"test\"}")); + } + + @Test + public void shouldReadReferenceWithLink() + { + String text = + "{" + + "\"name\": \"test\"," + + "\"links\":" + + "{" + + "\"self\": \"/test\"" + + "}" + + "}"; + + NamespaceRefConfig ref = jsonb.fromJson(text, NamespaceRefConfig.class); + + assertThat(ref, not(nullValue())); + assertThat(ref.name, equalTo("test")); + assertThat(ref.links, equalTo(singletonMap("self", "/test"))); + } + + + @Test + public void shouldWriteReferenceWithLink() + { + NamespaceRefConfig reference = NamespaceRefConfig.builder() + .inject(identity()) + .name("test") + .link("self", "/test") + .build(); + + String text = jsonb.toJson(reference); + + assertThat(text, not(nullValue())); + assertThat(text, equalTo("{\"name\":\"test\",\"links\":{\"self\":\"/test\"}}")); + } +} diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/OptionsConfigAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/OptionsConfigAdapterTest.java index b7d3dc080e..f7f2afaa45 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/OptionsConfigAdapterTest.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/OptionsConfigAdapterTest.java @@ -75,7 +75,9 @@ public void shouldReadOptions() @Test public void shouldWriteOptions() { - OptionsConfig options = new TestBindingOptionsConfig("test"); + OptionsConfig options = TestBindingOptionsConfig.builder() + .mode("test") + .build(); String text = jsonb.toJson(options); @@ -100,7 +102,9 @@ public void shouldReadNullWhenNotAdapting() @Test public void shouldWriteNullWhenNotAdapting() { - OptionsConfig options = new TestBindingOptionsConfig("test"); + OptionsConfig options = TestBindingOptionsConfig.builder() + .mode("test") + .build(); adapter.adaptType(null); String text = jsonb.toJson(options); diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/ReferenceConfigAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/ReferenceConfigAdapterTest.java deleted file mode 100644 index 01fa8db581..0000000000 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/ReferenceConfigAdapterTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.engine.internal.config; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; - -import jakarta.json.bind.Jsonb; -import jakarta.json.bind.JsonbBuilder; -import jakarta.json.bind.JsonbConfig; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; - -import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; - -public class ReferenceConfigAdapterTest -{ - @Rule - public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - @Mock - private ConfigAdapterContext context; - private Jsonb jsonb; - - @Before - public void initJson() - { - JsonbConfig config = new JsonbConfig() - .withAdapters(new NamspaceRefAdapter(context)); - jsonb = JsonbBuilder.create(config); - } - - @Test - public void shouldReadReference() - { - String text = - "{" + - "\"name\": \"test\"" + - "}"; - - NamespaceRef ref = jsonb.fromJson(text, NamespaceRef.class); - - assertThat(ref, not(nullValue())); - assertThat(ref.name, equalTo("test")); - assertThat(ref.links, equalTo(emptyMap())); - } - - - @Test - public void shouldWriteReference() - { - NamespaceRef route = new NamespaceRef("test", emptyMap()); - - String text = jsonb.toJson(route); - - assertThat(text, not(nullValue())); - assertThat(text, equalTo("{\"name\":\"test\"}")); - } - - @Test - public void shouldReadReferenceWithLink() - { - String text = - "{" + - "\"name\": \"test\"," + - "\"links\":" + - "{" + - "\"self\": \"/test\"" + - "}" + - "}"; - - NamespaceRef ref = jsonb.fromJson(text, NamespaceRef.class); - - assertThat(ref, not(nullValue())); - assertThat(ref.name, equalTo("test")); - assertThat(ref.links, equalTo(singletonMap("self", "/test"))); - } - - - @Test - public void shouldWriteReferenceWithLink() - { - NamespaceRef route = new NamespaceRef("test", singletonMap("self", "/test")); - - String text = jsonb.toJson(route); - - assertThat(text, not(nullValue())); - assertThat(text, equalTo("{\"name\":\"test\",\"links\":{\"self\":\"/test\"}}")); - } -} diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/RouteConfigAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/RouteConfigAdapterTest.java index bda6b90f4c..9ce6533307 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/RouteConfigAdapterTest.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/RouteConfigAdapterTest.java @@ -15,8 +15,8 @@ */ package io.aklivity.zilla.runtime.engine.internal.config; -import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; @@ -38,7 +38,6 @@ import org.mockito.quality.Strictness; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; -import io.aklivity.zilla.runtime.engine.config.GuardedConfig; import io.aklivity.zilla.runtime.engine.config.RouteConfig; import io.aklivity.zilla.runtime.engine.internal.config.ConditionConfigAdapterTest.TestConditionConfig; @@ -77,7 +76,9 @@ public void shouldReadRoute() @Test public void shouldWriteRoute() { - RouteConfig route = new RouteConfig("test"); + RouteConfig route = RouteConfig.builder() + .exit("test") + .build(); String text = jsonb.toJson(route); @@ -109,7 +110,15 @@ public void shouldReadRouteGuarded() @Test public void shouldWriteRouteGuarded() { - RouteConfig route = new RouteConfig("test", singletonList(new GuardedConfig("test", singletonList("role")))); + RouteConfig route = RouteConfig.builder() + .inject(identity()) + .exit("test") + .guarded() + .inject(identity()) + .name("test") + .role("role") + .build() + .build(); String text = jsonb.toJson(route); @@ -140,7 +149,14 @@ public void shouldReadRouteWhenMatch() @Test public void shouldWriteRouteWhenMatch() { - RouteConfig route = new RouteConfig("test", singletonList(new TestConditionConfig("test")), emptyList()); + RouteConfig route = RouteConfig.builder() + .inject(identity()) + .exit("test") + .when(TestConditionConfig::builder) + .inject(identity()) + .match("test") + .build() + .build(); String text = jsonb.toJson(route); diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryConfigsAdapterTest.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryConfigsAdapterTest.java index 66f2ee160b..78ea975eef 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryConfigsAdapterTest.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/config/TelemetryConfigsAdapterTest.java @@ -15,14 +15,13 @@ */ package io.aklivity.zilla.runtime.engine.internal.config; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; -import java.util.List; - import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; @@ -35,10 +34,7 @@ import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; -import io.aklivity.zilla.runtime.engine.config.AttributeConfig; import io.aklivity.zilla.runtime.engine.config.ConfigAdapterContext; -import io.aklivity.zilla.runtime.engine.config.ExporterConfig; -import io.aklivity.zilla.runtime.engine.config.MetricConfig; import io.aklivity.zilla.runtime.engine.config.TelemetryConfig; import io.aklivity.zilla.runtime.engine.test.internal.exporter.config.TestExporterOptionsConfig; @@ -105,11 +101,24 @@ public void shouldReadTelemetry() public void shouldWriteTelemetry() { // GIVEN - TelemetryConfig telemetry = new TelemetryConfig( - List.of(new AttributeConfig("test.attribute", "example")), - List.of(new MetricConfig("test", "test.counter")), - List.of(new ExporterConfig("test0", "test", null)) - ); + TelemetryConfig telemetry = TelemetryConfig.builder() + .inject(identity()) + .attribute() + .inject(identity()) + .name("test.attribute") + .value("example") + .build() + .metric() + .inject(identity()) + .group("test") + .name("test.counter") + .build() + .exporter() + .inject(identity()) + .name("test0") + .type("test") + .build() + .build(); // WHEN String text = jsonb.toJson(telemetry); @@ -171,11 +180,28 @@ public void shouldReadTelemetryWithExporterOptions() public void shouldWriteTelemetryWithExporterOptions() { // GIVEN - TelemetryConfig telemetry = new TelemetryConfig( - List.of(new AttributeConfig("test.attribute", "example")), - List.of(new MetricConfig("test", "test.counter")), - List.of(new ExporterConfig("test0", "test", new TestExporterOptionsConfig("test42"))) - ); + TelemetryConfig telemetry = TelemetryConfig.builder() + .inject(identity()) + .attribute() + .inject(identity()) + .name("test.attribute") + .value("example") + .build() + .metric() + .inject(identity()) + .group("test") + .name("test.counter") + .build() + .exporter() + .inject(identity()) + .name("test0") + .type("test") + .options(TestExporterOptionsConfig::builder) + .inject(identity()) + .mode("test42") + .build() + .build() + .build(); // WHEN String text = jsonb.toJson(telemetry); diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/EngineRule.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/EngineRule.java index 7c2ee1c211..0adfc1f262 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/EngineRule.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/EngineRule.java @@ -15,14 +15,11 @@ */ package io.aklivity.zilla.runtime.engine.test; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_COMMAND_BUFFER_CAPACITY; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_CONFIG_URL; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_COUNTERS_BUFFER_CAPACITY; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DIRECTORY; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_DRAIN_ON_CLOSE; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_RESPONSE_BUFFER_CAPACITY; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_ROUTED_DELAY_MILLIS; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_STREAMS_BUFFER_CAPACITY; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_SYNTHETIC_ABORT; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_WORKERS; import static java.nio.file.FileVisitOption.FOLLOW_LINKS; @@ -89,29 +86,16 @@ public EngineRule() configure(ENGINE_WORKERS, 1); } - public EngineRule directory(String directory) + public EngineRule directory( + String directory) { return configure(ENGINE_DIRECTORY, directory); } - public EngineRule commandBufferCapacity(int commandBufferCapacity) + public EngineRule countersBufferCapacity( + int countersBufferCapacity) { - return configure(ENGINE_COMMAND_BUFFER_CAPACITY, commandBufferCapacity); - } - - public EngineRule responseBufferCapacity(int responseBufferCapacity) - { - return configure(ENGINE_RESPONSE_BUFFER_CAPACITY, responseBufferCapacity); - } - - public EngineRule counterValuesBufferCapacity(int counterValuesBufferCapacity) - { - return configure(ENGINE_COUNTERS_BUFFER_CAPACITY, counterValuesBufferCapacity); - } - - public EngineRule streamsBufferCapacity(int streamsBufferCapacity) - { - return configure(ENGINE_STREAMS_BUFFER_CAPACITY, streamsBufferCapacity); + return configure(ENGINE_COUNTERS_BUFFER_CAPACITY, countersBufferCapacity); } public EngineRule configure( diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfig.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfig.java index 9e285e8be2..b40a76ec60 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfig.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfig.java @@ -15,13 +15,26 @@ */ package io.aklivity.zilla.runtime.engine.test.internal.binding.config; +import java.util.function.Function; + import io.aklivity.zilla.runtime.engine.config.OptionsConfig; public final class TestBindingOptionsConfig extends OptionsConfig { public final String mode; - public TestBindingOptionsConfig( + public static TestBindingOptionsConfigBuilder builder() + { + return new TestBindingOptionsConfigBuilder<>(TestBindingOptionsConfig.class::cast); + } + + public static TestBindingOptionsConfigBuilder builder( + Function mapper) + { + return new TestBindingOptionsConfigBuilder<>(mapper); + } + + TestBindingOptionsConfig( String mode) { this.mode = mode; diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfigAdapter.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfigAdapter.java index 26f6097f5e..e4b2b09630 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfigAdapter.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfigAdapter.java @@ -55,10 +55,16 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - String mode = object.containsKey(MODE_NAME) - ? object.getString(MODE_NAME) - : null; + TestBindingOptionsConfigBuilder testOptions = TestBindingOptionsConfig.builder(); - return new TestBindingOptionsConfig(mode); + if (object != null) + { + if (object.containsKey(MODE_NAME)) + { + testOptions.mode(object.getString(MODE_NAME)); + } + } + + return testOptions.build(); } } diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfigBuilder.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfigBuilder.java new file mode 100644 index 0000000000..b8ecf148aa --- /dev/null +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/binding/config/TestBindingOptionsConfigBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.test.internal.binding.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TestBindingOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String mode; + + TestBindingOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TestBindingOptionsConfigBuilder mode( + String mode) + { + this.mode = mode; + return this; + } + + @Override + public T build() + { + return mapper.apply(new TestBindingOptionsConfig(mode)); + } +} diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfig.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfig.java index 1bb9438eee..989b155ed7 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfig.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfig.java @@ -15,13 +15,26 @@ */ package io.aklivity.zilla.runtime.engine.test.internal.exporter.config; +import java.util.function.Function; + import io.aklivity.zilla.runtime.engine.config.OptionsConfig; public final class TestExporterOptionsConfig extends OptionsConfig { public final String mode; - public TestExporterOptionsConfig( + public static TestExporterOptionsConfigBuilder builder() + { + return new TestExporterOptionsConfigBuilder<>(TestExporterOptionsConfig.class::cast); + } + + public static TestExporterOptionsConfigBuilder builder( + Function mapper) + { + return new TestExporterOptionsConfigBuilder<>(mapper); + } + + TestExporterOptionsConfig( String mode) { this.mode = mode; diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfigAdapter.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfigAdapter.java index caf1cfe4b3..8694215761 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfigAdapter.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfigAdapter.java @@ -15,6 +15,8 @@ */ package io.aklivity.zilla.runtime.engine.test.internal.exporter.config; +import static java.util.function.Function.identity; + import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; @@ -55,9 +57,17 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - String mode = object != null && object.containsKey(MODE_NAME) - ? object.getString(MODE_NAME) - : null; - return new TestExporterOptionsConfig(mode); + TestExporterOptionsConfigBuilder testOptions = TestExporterOptionsConfig.builder() + .inject(identity()); + + if (object != null) + { + if (object.containsKey(MODE_NAME)) + { + testOptions.mode(object.getString(MODE_NAME)); + } + } + + return testOptions.build(); } } diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfigBuilder.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfigBuilder.java new file mode 100644 index 0000000000..27abc1cbca --- /dev/null +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/exporter/config/TestExporterOptionsConfigBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.test.internal.exporter.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TestExporterOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String mode; + + TestExporterOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TestExporterOptionsConfigBuilder mode( + String mode) + { + this.mode = mode; + return this; + } + + @Override + public T build() + { + return mapper.apply(new TestExporterOptionsConfig(mode)); + } +} diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardConfig.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardConfig.java index e3e1acfb11..31c573b47d 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardConfig.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardConfig.java @@ -15,16 +15,11 @@ */ package io.aklivity.zilla.runtime.engine.test.internal.guard; -import java.time.Duration; - import io.aklivity.zilla.runtime.engine.config.GuardConfig; import io.aklivity.zilla.runtime.engine.test.internal.guard.config.TestGuardOptionsConfig; public final class TestGuardConfig { - public static final Duration DEFAULT_CHALLENGE_NEVER = Duration.ofMillis(0L); - public static final Duration DEFAULT_LIFETIME_FOREVER = Duration.ofMillis(Long.MAX_VALUE); - public final TestGuardOptionsConfig options; public TestGuardConfig( diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardHandler.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardHandler.java index b3bb14842a..1e872dfcdd 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardHandler.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/TestGuardHandler.java @@ -15,8 +15,8 @@ */ package io.aklivity.zilla.runtime.engine.test.internal.guard; -import static io.aklivity.zilla.runtime.engine.test.internal.guard.TestGuardConfig.DEFAULT_CHALLENGE_NEVER; -import static io.aklivity.zilla.runtime.engine.test.internal.guard.TestGuardConfig.DEFAULT_LIFETIME_FOREVER; +import static io.aklivity.zilla.runtime.engine.test.internal.guard.config.TestGuardOptionsConfigBuilder.DEFAULT_CHALLENGE_NEVER; +import static io.aklivity.zilla.runtime.engine.test.internal.guard.config.TestGuardOptionsConfigBuilder.DEFAULT_LIFETIME_FOREVER; import java.time.Duration; import java.time.Instant; diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfig.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfig.java index 581f232355..69d6132e89 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfig.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfig.java @@ -18,6 +18,7 @@ import java.time.Duration; import java.util.List; import java.util.Objects; +import java.util.function.Function; import io.aklivity.zilla.runtime.engine.config.OptionsConfig; @@ -28,7 +29,18 @@ public final class TestGuardOptionsConfig extends OptionsConfig public final Duration challenge; public final List roles; - public TestGuardOptionsConfig( + public static TestGuardOptionsConfigBuilder builder() + { + return new TestGuardOptionsConfigBuilder<>(TestGuardOptionsConfig.class::cast); + } + + public static TestGuardOptionsConfigBuilder builder( + Function mapper) + { + return new TestGuardOptionsConfigBuilder<>(mapper); + } + + TestGuardOptionsConfig( String credentials, Duration lifetime, Duration challenge, diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfigAdapter.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfigAdapter.java index c14d30b6ba..e713bfd13a 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfigAdapter.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfigAdapter.java @@ -15,15 +15,12 @@ */ package io.aklivity.zilla.runtime.engine.test.internal.guard.config; -import static io.aklivity.zilla.runtime.engine.test.internal.guard.TestGuardConfig.DEFAULT_CHALLENGE_NEVER; -import static io.aklivity.zilla.runtime.engine.test.internal.guard.TestGuardConfig.DEFAULT_LIFETIME_FOREVER; +import static io.aklivity.zilla.runtime.engine.test.internal.guard.config.TestGuardOptionsConfigBuilder.DEFAULT_CHALLENGE_NEVER; +import static io.aklivity.zilla.runtime.engine.test.internal.guard.config.TestGuardOptionsConfigBuilder.DEFAULT_LIFETIME_FOREVER; import java.time.Duration; -import java.util.ArrayList; -import java.util.List; import jakarta.json.Json; -import jakarta.json.JsonArray; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; @@ -87,32 +84,34 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - String newCredentials = object.containsKey(CREDENTIALS_NAME) - ? object.getString(CREDENTIALS_NAME) - : null; + TestGuardOptionsConfigBuilder testOptions = TestGuardOptionsConfig.builder(); - Duration newLifetime = object.containsKey(LIFETIME_NAME) - ? Duration.parse(object.getString(LIFETIME_NAME)) - : DEFAULT_LIFETIME_FOREVER; - - Duration newChallenge = object.containsKey(CHALLENGE_NAME) - ? Duration.parse(object.getString(CHALLENGE_NAME)) - : DEFAULT_CHALLENGE_NEVER; - - JsonArray roles = object.containsKey(ROLES_NAME) - ? object.getJsonArray(ROLES_NAME) - : null; - - List newRoles = null; - - if (roles != null) + if (object != null) { - List newRoles0 = new ArrayList<>(); - roles.forEach(v -> - newRoles0.add(JsonString.class.cast(v).getString())); - newRoles = newRoles0; + if (object.containsKey(CREDENTIALS_NAME)) + { + testOptions.credentials(object.getString(CREDENTIALS_NAME)); + } + + if (object.containsKey(LIFETIME_NAME)) + { + testOptions.lifetime(Duration.parse(object.getString(LIFETIME_NAME))); + } + + if (object.containsKey(CHALLENGE_NAME)) + { + testOptions.challenge(Duration.parse(object.getString(CHALLENGE_NAME))); + } + + if (object.containsKey(ROLES_NAME)) + { + object.getJsonArray(ROLES_NAME).stream() + .map(JsonString.class::cast) + .map(JsonString::getString) + .forEach(testOptions::role); + } } - return new TestGuardOptionsConfig(newCredentials, newLifetime, newChallenge, newRoles); + return testOptions.build(); } } diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfigBuilder.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfigBuilder.java new file mode 100644 index 0000000000..314fb0ff8f --- /dev/null +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/guard/config/TestGuardOptionsConfigBuilder.java @@ -0,0 +1,95 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.test.internal.guard.config; + +import java.time.Duration; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TestGuardOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String credentials; + private Duration lifetime; + private Duration challenge; + private List roles; + + public static final Duration DEFAULT_CHALLENGE_NEVER = Duration.ofMillis(0L); + + public static final Duration DEFAULT_LIFETIME_FOREVER = Duration.ofMillis(Long.MAX_VALUE); + + TestGuardOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TestGuardOptionsConfigBuilder credentials( + String credentials) + { + this.credentials = credentials; + return this; + } + + public TestGuardOptionsConfigBuilder lifetime( + Duration lifetime) + { + this.lifetime = lifetime; + return this; + } + + public TestGuardOptionsConfigBuilder challenge( + Duration challenge) + { + this.challenge = Objects.requireNonNull(challenge); + return this; + } + + public TestGuardOptionsConfigBuilder role( + String role) + { + if (roles == null) + { + roles = new LinkedList<>(); + } + roles.add(role); + return this; + } + + @Override + public T build() + { + return mapper.apply(new TestGuardOptionsConfig( + credentials, + Optional.ofNullable(lifetime).orElse(DEFAULT_LIFETIME_FOREVER), + Optional.ofNullable(challenge).orElse(DEFAULT_CHALLENGE_NEVER), + roles)); + } +} diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfig.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfig.java index 024fbef878..a763bb3b0c 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfig.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfig.java @@ -15,13 +15,26 @@ */ package io.aklivity.zilla.runtime.engine.test.internal.vault.config; +import java.util.function.Function; + import io.aklivity.zilla.runtime.engine.config.OptionsConfig; public final class TestVaultOptionsConfig extends OptionsConfig { public final String mode; - public TestVaultOptionsConfig( + public static TestVaultOptionsConfigBuilder builder() + { + return new TestVaultOptionsConfigBuilder<>(TestVaultOptionsConfig.class::cast); + } + + public static TestVaultOptionsConfigBuilder builder( + Function mapper) + { + return new TestVaultOptionsConfigBuilder<>(mapper); + } + + TestVaultOptionsConfig( String mode) { this.mode = mode; diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfigAdapter.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfigAdapter.java index e9397fa9db..46eac521ba 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfigAdapter.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfigAdapter.java @@ -55,10 +55,16 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - String mode = object.containsKey(MODE_NAME) - ? object.getString(MODE_NAME) - : null; + TestVaultOptionsConfigBuilder testOptions = TestVaultOptionsConfig.builder(); - return new TestVaultOptionsConfig(mode); + if (object != null) + { + if (object.containsKey(MODE_NAME)) + { + testOptions.mode(object.getString(MODE_NAME)); + } + } + + return testOptions.build(); } } diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfigBuilder.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfigBuilder.java new file mode 100644 index 0000000000..35a2545b8e --- /dev/null +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/test/internal/vault/config/TestVaultOptionsConfigBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.engine.test.internal.vault.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class TestVaultOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String mode; + + TestVaultOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public TestVaultOptionsConfigBuilder mode( + String mode) + { + this.mode = mode; + return this; + } + + @Override + public T build() + { + return mapper.apply(new TestVaultOptionsConfig(mode)); + } +} diff --git a/runtime/engine/src/test/resources/io/aklivity/zilla/runtime/engine/internal/EngineTest-duplicate-key.broken.json b/runtime/engine/src/test/resources/io/aklivity/zilla/runtime/engine/internal/EngineTest-duplicate-key.broken.json index f826157e37..1218659165 100644 --- a/runtime/engine/src/test/resources/io/aklivity/zilla/runtime/engine/internal/EngineTest-duplicate-key.broken.json +++ b/runtime/engine/src/test/resources/io/aklivity/zilla/runtime/engine/internal/EngineTest-duplicate-key.broken.json @@ -1,4 +1,5 @@ { + "name": "duplicate-key", "bindings": { "test0": diff --git a/runtime/exporter-prometheus/pom.xml b/runtime/exporter-prometheus/pom.xml index 7537bbda7b..0959fd136b 100644 --- a/runtime/exporter-prometheus/pom.xml +++ b/runtime/exporter-prometheus/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/exporter-prometheus/src/main/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/config/PrometheusEndpointConfig.java b/runtime/exporter-prometheus/src/main/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/config/PrometheusEndpointConfig.java index 4e05c2d7aa..c8a04843e6 100644 --- a/runtime/exporter-prometheus/src/main/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/config/PrometheusEndpointConfig.java +++ b/runtime/exporter-prometheus/src/main/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/config/PrometheusEndpointConfig.java @@ -14,9 +14,7 @@ */ package io.aklivity.zilla.runtime.exporter.prometheus.internal.config; -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public class PrometheusEndpointConfig extends OptionsConfig +public class PrometheusEndpointConfig { public String scheme; public int port; diff --git a/runtime/exporter-prometheus/src/test/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/PrometheusExporterHandlerTest.java b/runtime/exporter-prometheus/src/test/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/PrometheusExporterHandlerTest.java index 4e7230f6ca..0068e0c0da 100644 --- a/runtime/exporter-prometheus/src/test/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/PrometheusExporterHandlerTest.java +++ b/runtime/exporter-prometheus/src/test/java/io/aklivity/zilla/runtime/exporter/prometheus/internal/PrometheusExporterHandlerTest.java @@ -51,7 +51,11 @@ public void shouldStart() throws Exception EngineContext context = mock(EngineContext.class); PrometheusEndpointConfig endpoint = new PrometheusEndpointConfig("http", 4242, "/metrics"); PrometheusOptionsConfig options = new PrometheusOptionsConfig(new PrometheusEndpointConfig[]{endpoint}); - ExporterConfig exporter = new ExporterConfig("test0", "prometheus", options); + ExporterConfig exporter = ExporterConfig.builder() + .name("test0") + .type("prometheus") + .options(options) + .build(); PrometheusExporterConfig prometheusExporter = new PrometheusExporterConfig(exporter); Collector collector = mock(Collector.class); when(collector.counterIds()).thenReturn(new long[][]{}); diff --git a/runtime/guard-jwt/pom.xml b/runtime/guard-jwt/pom.xml index a766ec3cfa..fe5518c2ac 100644 --- a/runtime/guard-jwt/pom.xml +++ b/runtime/guard-jwt/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeyConfig.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeyConfig.java similarity index 83% rename from runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeyConfig.java rename to runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeyConfig.java index 764b9fe8cd..36cc97c244 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeyConfig.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeyConfig.java @@ -12,7 +12,9 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.guard.jwt.internal.config; +package io.aklivity.zilla.runtime.guard.jwt.config; + +import static java.util.function.Function.identity; public class JwtKeyConfig { @@ -26,7 +28,12 @@ public class JwtKeyConfig public final String x; public final String y; - public JwtKeyConfig( + public static JwtKeyConfigBuilder builder() + { + return new JwtKeyConfigBuilder<>(identity()); + } + + JwtKeyConfig( String kty, String kid, String use, diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeyConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeyConfigBuilder.java new file mode 100644 index 0000000000..c95bf3acce --- /dev/null +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeyConfigBuilder.java @@ -0,0 +1,116 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.guard.jwt.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public class JwtKeyConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String alg; + private String kty; + private String kid; + private String use; + private String n; + private String e; + private String crv; + private String x; + private String y; + + JwtKeyConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public JwtKeyConfigBuilder kty( + String kty) + { + this.kty = kty; + return this; + } + + public JwtKeyConfigBuilder kid( + String kid) + { + this.kid = kid; + return this; + } + + public JwtKeyConfigBuilder use( + String use) + { + this.use = use; + return this; + } + + public JwtKeyConfigBuilder n( + String n) + { + this.n = n; + return this; + } + + public JwtKeyConfigBuilder e( + String e) + { + this.e = e; + return this; + } + + public JwtKeyConfigBuilder alg( + String alg) + { + this.alg = alg; + return this; + } + + public JwtKeyConfigBuilder crv( + String crv) + { + this.crv = crv; + return this; + } + + public JwtKeyConfigBuilder x( + String x) + { + this.x = x; + return this; + } + + public JwtKeyConfigBuilder y( + String y) + { + this.y = y; + return this; + } + + @Override + public T build() + { + return mapper.apply(new JwtKeyConfig(kty, kid, use, n, e, alg, crv, x, y)); + } +} diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfig.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeySetConfig.java similarity index 92% rename from runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfig.java rename to runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeySetConfig.java index 0e8ff0ca36..269fc1356c 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfig.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtKeySetConfig.java @@ -12,7 +12,7 @@ * WARRANTIES OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package io.aklivity.zilla.runtime.guard.jwt.internal.config; +package io.aklivity.zilla.runtime.guard.jwt.config; import java.util.List; diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java new file mode 100644 index 0000000000..2ac7787f91 --- /dev/null +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.guard.jwt.config; + +import static java.util.Optional.ofNullable; + +import java.time.Duration; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public class JwtOptionsConfig extends OptionsConfig +{ + public final String issuer; + public final String audience; + public final List keys; + public final Optional challenge; + public final Optional keysURL; + + public static JwtOptionsConfigBuilder builder() + { + return new JwtOptionsConfigBuilder<>(JwtOptionsConfig.class::cast); + } + + public static JwtOptionsConfigBuilder builder( + Function mapper) + { + return new JwtOptionsConfigBuilder<>(mapper); + } + + JwtOptionsConfig( + String issuer, + String audience, + List keys, + Duration challenge, + String keysURL) + { + this.issuer = issuer; + this.audience = audience; + this.keys = keys; + this.challenge = ofNullable(challenge); + this.keysURL = ofNullable(keysURL); + } +} diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java new file mode 100644 index 0000000000..7ae6d40e22 --- /dev/null +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java @@ -0,0 +1,104 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.guard.jwt.config; + +import java.time.Duration; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public class JwtOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String issuer; + private String audience; + private List keys; + private Duration challenge; + private String keysURL; + + JwtOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public JwtOptionsConfigBuilder issuer( + String issuer) + { + this.issuer = issuer; + return this; + } + + public JwtOptionsConfigBuilder audience( + String audience) + { + this.audience = audience; + return this; + } + + public JwtOptionsConfigBuilder challenge( + Duration challenge) + { + this.challenge = challenge; + return this; + } + + public JwtOptionsConfigBuilder keys( + List keys) + { + this.keys = keys; + return this; + } + + public JwtKeyConfigBuilder> key() + { + return new JwtKeyConfigBuilder<>(this::key); + } + + public JwtOptionsConfigBuilder key( + JwtKeyConfig key) + { + if (keys == null) + { + keys = new LinkedList<>(); + } + keys.add(key); + return this; + } + + public JwtOptionsConfigBuilder keysURL( + String keysURL) + { + this.keysURL = keysURL; + return this; + } + + @Override + public T build() + { + return mapper.apply(new JwtOptionsConfig(issuer, audience, keys, challenge, keysURL)); + } +} diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardContext.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardContext.java index 0d6cf7f4f0..1412213c25 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardContext.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardContext.java @@ -22,7 +22,7 @@ import io.aklivity.zilla.runtime.engine.EngineContext; import io.aklivity.zilla.runtime.engine.config.GuardConfig; import io.aklivity.zilla.runtime.engine.guard.GuardContext; -import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtOptionsConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; final class JwtGuardContext implements GuardContext { diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index db5619973a..54f2358905 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -43,10 +43,10 @@ import org.jose4j.lang.JoseException; import io.aklivity.zilla.runtime.engine.guard.GuardHandler; -import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtKeyConfig; -import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtKeySetConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeyConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeySetConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtKeySetConfigAdapter; -import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtOptionsConfig; public class JwtGuardHandler implements GuardHandler { diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeyConfigAdapter.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeyConfigAdapter.java index 51a7e7546a..46591af28a 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeyConfigAdapter.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeyConfigAdapter.java @@ -19,6 +19,9 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeyConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeyConfigBuilder; + public final class JwtKeyConfigAdapter implements JsonbAdapter { private static final String ALG_NAME = "alg"; @@ -83,18 +86,45 @@ public JsonObject adaptToJson( public JwtKeyConfig adaptFromJson( JsonObject object) { - String kty = object.getString(KTY_NAME); - String kid = object.getString(KID_NAME); - String use = object.containsKey(USE_NAME) ? object.getString(USE_NAME) : null; + JwtKeyConfigBuilder jwtKey = JwtKeyConfig.builder() + .kty(object.getString(KTY_NAME)) + .kid(object.getString(KID_NAME)); + + if (object.containsKey(USE_NAME)) + { + jwtKey.use(object.getString(USE_NAME)); + } + + if (object.containsKey(N_NAME)) + { + jwtKey.n(object.getString(N_NAME)); + } + + if (object.containsKey(E_NAME)) + { + jwtKey.e(object.getString(E_NAME)); + } - String n = object.containsKey(N_NAME) ? object.getString(N_NAME) : null; - String e = object.containsKey(E_NAME) ? object.getString(E_NAME) : null; - String alg = object.containsKey(ALG_NAME) ? object.getString(ALG_NAME) : null; + if (object.containsKey(ALG_NAME)) + { + jwtKey.alg(object.getString(ALG_NAME)); + } + + if (object.containsKey(CRV_NAME)) + { + jwtKey.crv(object.getString(CRV_NAME)); + } - String crv = object.containsKey(CRV_NAME) ? object.getString(CRV_NAME) : null; - String x = object.containsKey(X_NAME) ? object.getString(X_NAME) : null; - String y = object.containsKey(Y_NAME) ? object.getString(Y_NAME) : null; + if (object.containsKey(X_NAME)) + { + jwtKey.x(object.getString(X_NAME)); + } + + if (object.containsKey(Y_NAME)) + { + jwtKey.y(object.getString(Y_NAME)); + } - return new JwtKeyConfig(kty, kid, use, n, e, alg, crv, x, y); + return jwtKey.build(); } } diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapter.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapter.java index d8ef3f5dc6..d554efe2b4 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapter.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapter.java @@ -25,6 +25,9 @@ import jakarta.json.JsonValue; import jakarta.json.bind.adapter.JsonbAdapter; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeyConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeySetConfig; + public final class JwtKeySetConfigAdapter implements JsonbAdapter { private static final String KEYS_NAME = "keys"; diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfig.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfig.java deleted file mode 100644 index 302cd94c7c..0000000000 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc - * - * Licensed under the Aklivity Community License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of the - * License at - * - * https://www.aklivity.io/aklivity-community-license/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package io.aklivity.zilla.runtime.guard.jwt.internal.config; - -import static java.util.Optional.ofNullable; - -import java.time.Duration; -import java.util.List; -import java.util.Optional; - -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public class JwtOptionsConfig extends OptionsConfig -{ - public final String issuer; - public final String audience; - public final List keys; - public final Optional challenge; - - public final Optional keysURL; - - public JwtOptionsConfig( - String issuer, - String audience, - List keys, - Duration challenge) - { - this(issuer, audience, keys, challenge, null); - } - - public JwtOptionsConfig( - String issuer, - String audience, - List keys, - Duration challenge, - String keysURL) - { - this.issuer = issuer; - this.audience = audience; - this.keys = keys; - this.challenge = ofNullable(challenge); - this.keysURL = ofNullable(keysURL); - } -} diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java index d9d1e47844..8c6330c1b3 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java @@ -15,12 +15,10 @@ package io.aklivity.zilla.runtime.guard.jwt.internal.config; import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toList; import java.time.Duration; import java.util.List; - import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; @@ -31,6 +29,9 @@ import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeyConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfigBuilder; import io.aklivity.zilla.runtime.guard.jwt.internal.JwtGuard; public final class JwtOptionsConfigAdapter implements OptionsConfigAdapterSpi, JsonbAdapter @@ -98,47 +99,56 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - String issuer = object.containsKey(ISSUER_NAME) - ? object.getString(ISSUER_NAME) - : null; + JwtOptionsConfigBuilder jwtOptions = JwtOptionsConfig.builder(); - String audience = object.containsKey(AUDIENCE_NAME) - ? object.getString(AUDIENCE_NAME) - : null; + String issuer = object.containsKey(ISSUER_NAME) ? object.getString(ISSUER_NAME) : null; + if (issuer != null) + { + jwtOptions.issuer(issuer); + } + + if (object.containsKey(AUDIENCE_NAME)) + { + jwtOptions.audience(object.getString(AUDIENCE_NAME)); + } - List keys = KEYS_DEFAULT; - String keysURL = null; if (object.containsKey(KEYS_NAME)) { JsonValue keysValue = object.getValue(String.format("/%s", KEYS_NAME)); switch (keysValue.getValueType()) { case ARRAY: - keys = keysValue.asJsonArray() - .stream() - .map(JsonValue::asJsonObject) - .map(key::adaptFromJson) - .collect(toList()); + keysValue.asJsonArray() + .stream() + .map(JsonValue::asJsonObject) + .map(key::adaptFromJson) + .forEach(jwtOptions::key); break; case STRING: - keysURL = ((JsonString) keysValue).getString(); + jwtOptions.keys(KEYS_DEFAULT) + .keysURL(((JsonString) keysValue).getString()); + break; + default: break; } } else { + jwtOptions.keys(KEYS_DEFAULT); + if (issuer != null) { - keysURL = issuer.endsWith("/") + jwtOptions.keysURL(issuer.endsWith("/") ? String.format("%s.well-known/jwks.json", issuer) - : String.format("%s/.well-known/jwks.json", issuer); + : String.format("%s/.well-known/jwks.json", issuer)); } } - Duration challenge = object.containsKey(CHALLENGE_NAME) - ? Duration.ofSeconds(object.getInt(CHALLENGE_NAME)) - : null; + if (object.containsKey(CHALLENGE_NAME)) + { + jwtOptions.challenge(Duration.ofSeconds(object.getInt(CHALLENGE_NAME))); + } - return new JwtOptionsConfig(issuer, audience, keys, challenge, keysURL); + return jwtOptions.build(); } } diff --git a/runtime/guard-jwt/src/main/moditect/module-info.java b/runtime/guard-jwt/src/main/moditect/module-info.java index 200457b394..0d9410c4d4 100644 --- a/runtime/guard-jwt/src/main/moditect/module-info.java +++ b/runtime/guard-jwt/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ requires io.aklivity.zilla.runtime.engine; requires org.jose4j; + exports io.aklivity.zilla.runtime.guard.jwt.config; + provides io.aklivity.zilla.runtime.engine.guard.GuardFactorySpi with io.aklivity.zilla.runtime.guard.jwt.internal.JwtGuardFactorySpi; diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java index 5fe73952bf..88649c6a63 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java @@ -18,7 +18,7 @@ import static io.aklivity.zilla.specs.guard.jwt.keys.JwtKeys.RFC7515_RS256; import static java.time.Duration.ofSeconds; import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -36,7 +36,7 @@ import org.jose4j.lang.JoseException; import org.junit.Test; -import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtOptionsConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; public class JwtGuardHandlerTest { @@ -46,8 +46,13 @@ public class JwtGuardHandlerTest public void shouldAuthorize() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -74,8 +79,13 @@ public void shouldAuthorize() throws Exception public void shouldChallengeDuringChallengeWindow() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -98,8 +108,13 @@ public void shouldChallengeDuringChallengeWindow() throws Exception public void shouldNotChallengeDuringWindowWithoutSubject() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -121,8 +136,13 @@ public void shouldNotChallengeDuringWindowWithoutSubject() throws Exception public void shouldNotChallengeBeforeChallengeWindow() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -145,8 +165,13 @@ public void shouldNotChallengeBeforeChallengeWindow() throws Exception public void shouldNotChallengeAgainDuringChallengeWindow() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -170,7 +195,12 @@ public void shouldNotChallengeAgainDuringChallengeWindow() throws Exception @Test public void shouldNotAuthorizeWhenAlgorithmDiffers() throws Exception { - JwtOptionsConfig options = new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), null); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); JwtClaims claims = new JwtClaims(); @@ -187,7 +217,12 @@ public void shouldNotAuthorizeWhenAlgorithmDiffers() throws Exception @Test public void shouldNotAuthorizeWhenSignatureInvalid() throws Exception { - JwtOptionsConfig options = new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), null); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); JwtClaims claims = new JwtClaims(); @@ -206,7 +241,12 @@ public void shouldNotAuthorizeWhenSignatureInvalid() throws Exception @Test public void shouldNotAuthorizeWhenIssuerDiffers() throws Exception { - JwtOptionsConfig options = new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), null); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); JwtClaims claims = new JwtClaims(); @@ -223,7 +263,12 @@ public void shouldNotAuthorizeWhenIssuerDiffers() throws Exception @Test public void shouldNotAuthorizeWhenAudienceDiffers() throws Exception { - JwtOptionsConfig options = new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), null); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); JwtClaims claims = new JwtClaims(); @@ -240,7 +285,12 @@ public void shouldNotAuthorizeWhenAudienceDiffers() throws Exception @Test public void shouldNotAuthorizeWhenExpired() throws Exception { - JwtOptionsConfig options = new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), null); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -260,7 +310,12 @@ public void shouldNotAuthorizeWhenExpired() throws Exception @Test public void shouldNotAuthorizeWhenNotYetValid() throws Exception { - JwtOptionsConfig options = new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), null); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -281,8 +336,13 @@ public void shouldNotAuthorizeWhenNotYetValid() throws Exception public void shouldNotVerifyAuthorizedWhenRolesInsufficient() throws Exception { Duration challenge = ofSeconds(30L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); JwtClaims claims = new JwtClaims(); @@ -302,8 +362,13 @@ public void shouldNotVerifyAuthorizedWhenRolesInsufficient() throws Exception public void shouldReauthorizeWhenExpirationLater() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -332,8 +397,13 @@ public void shouldReauthorizeWhenExpirationLater() throws Exception public void shouldReauthorizeWhenScopeBroader() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -363,8 +433,13 @@ public void shouldReauthorizeWhenScopeBroader() throws Exception public void shouldNotReauthorizeWhenExpirationEarlier() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -393,8 +468,13 @@ public void shouldNotReauthorizeWhenExpirationEarlier() throws Exception public void shouldNotReauthorizeWhenScopeNarrower() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -425,8 +505,13 @@ public void shouldNotReauthorizeWhenScopeNarrower() throws Exception public void shouldNotReauthorizeWhenSubjectDiffers() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -457,8 +542,13 @@ public void shouldNotReauthorizeWhenSubjectDiffers() throws Exception public void shouldNotReauthorizeWhenContextDiffers() throws Exception { Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); @@ -488,8 +578,13 @@ public void shouldNotReauthorizeWhenContextDiffers() throws Exception public void shouldDeauthorize() throws Exception { Duration challenge = ofSeconds(30L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); JwtGuardHandler guard = new JwtGuardHandler(options, new MutableLong(1L)::getAndIncrement, READ_KEYS_URL); Instant now = Instant.now(); diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardIT.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardIT.java index a90c7ffee8..c89f04281c 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardIT.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardIT.java @@ -32,9 +32,7 @@ public class JwtGuardIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/guard/jwt/config") .clean(); diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java index 54562a4dbe..9850e10543 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java @@ -18,8 +18,7 @@ import static io.aklivity.zilla.runtime.guard.jwt.internal.keys.JwtKeyConfigs.RFC7515_RS256_CONFIG; import static io.aklivity.zilla.specs.guard.jwt.keys.JwtKeys.RFC7515_RS256; import static java.time.Duration.ofSeconds; -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -42,14 +41,19 @@ import io.aklivity.zilla.runtime.engine.guard.GuardContext; import io.aklivity.zilla.runtime.engine.guard.GuardFactory; import io.aklivity.zilla.runtime.engine.guard.GuardHandler; -import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtOptionsConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; public class JwtGuardTest { @Test public void shouldNotVerifyMissingContext() throws Exception { - GuardedConfig guarded = new GuardedConfig("test0", asList("read:stream", "write:stream")); + GuardedConfig guarded = GuardedConfig.builder() + .inject(identity()) + .name("test0") + .role("read:stream") + .role("write:stream") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); @@ -67,7 +71,12 @@ public void shouldNotVerifyMissingHandler() throws Exception when(engine.index()).thenReturn(0); - GuardedConfig guarded = new GuardedConfig("test0", asList("read:stream", "write:stream")); + GuardedConfig guarded = GuardedConfig.builder() + .inject(identity()) + .name("test0") + .role("read:stream") + .role("write:stream") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); @@ -87,14 +96,24 @@ public void shouldNotVerifyMissingSession() throws Exception when(engine.index()).thenReturn(0); - GuardedConfig guarded = new GuardedConfig("test0", asList("read:stream", "write:stream")); + GuardedConfig guarded = GuardedConfig.builder() + .inject(identity()) + .name("test0") + .role("read:stream") + .role("write:stream") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); Guard guard = factory.create("jwt", config); GuardContext context = guard.supply(engine); - context.attach(new GuardConfig("test0", "jwt", new JwtOptionsConfig(null, null, null, null))); + context.attach(GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig.builder().build()) + .build()); LongPredicate verifier = guard.verifier(s -> 0, guarded); @@ -108,7 +127,11 @@ public void shouldNotVerifyRolesWhenInsufficient() throws Exception when(engine.index()).thenReturn(0); - GuardedConfig guarded = new GuardedConfig("test0", asList("read:stream", "write:stream")); + GuardedConfig guarded = GuardedConfig.builder() + .name("test0") + .role("read:stream") + .role("write:stream") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); @@ -116,10 +139,18 @@ public void shouldNotVerifyRolesWhenInsufficient() throws Exception GuardContext context = guard.supply(engine); - Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); - GuardHandler handler = context.attach(new GuardConfig("test0", "jwt", options)); + GuardHandler handler = context.attach(GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(ofSeconds(3L)) + .build() + .build()); LongPredicate verifier = guard.verifier(s -> 0, guarded); @@ -147,7 +178,12 @@ public void shouldVerifyRolesWhenExact() throws Exception when(engine.index()).thenReturn(0); when(engine.supplyAuthorizedId()).thenReturn(1L); - GuardedConfig guarded = new GuardedConfig("test0", asList("read:stream", "write:stream")); + GuardedConfig guarded = GuardedConfig.builder() + .inject(identity()) + .name("test0") + .role("read:stream") + .role("write:stream") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); @@ -155,10 +191,18 @@ public void shouldVerifyRolesWhenExact() throws Exception GuardContext context = guard.supply(engine); - Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); - GuardHandler handler = context.attach(new GuardConfig("test0", "jwt", options)); + GuardHandler handler = context.attach(GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(ofSeconds(3L)) + .build() + .build()); LongPredicate verifier = guard.verifier(s -> 0, guarded); @@ -186,7 +230,11 @@ public void shouldVerifyRolesWhenSuperset() throws Exception when(engine.index()).thenReturn(0); when(engine.supplyAuthorizedId()).thenReturn(1L); - GuardedConfig guarded = new GuardedConfig("test0", asList("read:stream")); + GuardedConfig guarded = GuardedConfig.builder() + .inject(identity()) + .name("test0") + .role("read:stream") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); @@ -194,10 +242,18 @@ public void shouldVerifyRolesWhenSuperset() throws Exception GuardContext context = guard.supply(engine); - Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); - GuardHandler handler = context.attach(new GuardConfig("test0", "jwt", options)); + GuardHandler handler = context.attach(GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(ofSeconds(3L)) + .build() + .build()); LongPredicate verifier = guard.verifier(s -> 0, guarded); @@ -225,7 +281,10 @@ public void shouldVerifyRolesWhenEmpty() throws Exception when(engine.index()).thenReturn(0); when(engine.supplyAuthorizedId()).thenReturn(1L); - GuardedConfig guarded = new GuardedConfig("test0", asList()); + GuardedConfig guarded = GuardedConfig.builder() + .inject(identity()) + .name("test0") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); @@ -233,10 +292,18 @@ public void shouldVerifyRolesWhenEmpty() throws Exception GuardContext context = guard.supply(engine); - Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); - GuardHandler handler = context.attach(new GuardConfig("test0", "jwt", options)); + GuardHandler handler = context.attach(GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(ofSeconds(3L)) + .build() + .build()); LongPredicate verifier = guard.verifier(s -> 0, guarded); @@ -269,14 +336,24 @@ public void shouldVerifyWhenIndexDiffers() throws Exception GuardContext context = guard.supply(engine); - Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); - GuardConfig config = new GuardConfig("test0", "jwt", options); + GuardConfig config = GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(ofSeconds(3L)) + .build() + .build(); config.id = 0x11L; GuardHandler handler = context.attach(config); - GuardedConfig guarded = new GuardedConfig("test0", asList()); + GuardedConfig guarded = GuardedConfig.builder() + .name("test0") + .build(); guarded.id = config.id; LongPredicate verifier = guard.verifier(id -> (int)(id >> 4), guarded); @@ -304,7 +381,10 @@ public void shouldIdentify() throws Exception when(engine.index()).thenReturn(0); when(engine.supplyAuthorizedId()).thenReturn(1L); - GuardedConfig guarded = new GuardedConfig("test0", asList()); + GuardedConfig guarded = GuardedConfig.builder() + .inject(identity()) + .name("test0") + .build(); Configuration config = new Configuration(); GuardFactory factory = GuardFactory.instantiate(); @@ -312,10 +392,18 @@ public void shouldIdentify() throws Exception GuardContext context = guard.supply(engine); - Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); - GuardHandler handler = context.attach(new GuardConfig("test0", "jwt", options)); + GuardHandler handler = context.attach(GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(ofSeconds(3L)) + .build() + .build()); LongFunction identifier = guard.identifier(s -> 0, guarded); @@ -349,12 +437,23 @@ public void shouldIdentifyWhenIndexDiffers() throws Exception GuardContext context = guard.supply(engine); Duration challenge = ofSeconds(3L); - JwtOptionsConfig options = - new JwtOptionsConfig("test issuer", "testAudience", singletonList(RFC7515_RS256_CONFIG), challenge); - GuardConfig config = new GuardConfig("test0", "jwt", options); + GuardConfig config = GuardConfig.builder() + .inject(identity()) + .name("test0") + .type("jwt") + .options(JwtOptionsConfig::builder) + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build() + .build(); config.id = 0x11L; - GuardedConfig guarded = new GuardedConfig("test0", asList()); + GuardedConfig guarded = GuardedConfig.builder() + .name("test0") + .build(); guarded.id = config.id; GuardHandler handler = context.attach(config); diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapterTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapterTest.java index d5a2a3d968..225813bc1e 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapterTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtKeySetConfigAdapterTest.java @@ -31,6 +31,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeySetConfig; + public class JwtKeySetConfigAdapterTest { private Jsonb jsonb; diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java index 91325631f7..e1df7ba43a 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java @@ -14,7 +14,6 @@ */ package io.aklivity.zilla.runtime.guard.jwt.internal.config; -import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; @@ -31,6 +30,8 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfig; + public class JwtOptionsConfigAdapterTest { private Jsonb jsonb; @@ -103,24 +104,31 @@ public void shouldReadOptions() @Test public void shouldWriteOptions() { - JwtKeyConfig key0 = new JwtKeyConfig( - "EC", "1", "enc", - null, null, null, - "P-256", "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"); - JwtKeyConfig key1 = new JwtKeyConfig( - "RSA", "2011-04-29", null, - "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx" + - "4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs" + - "tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2" + - "QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI" + - "SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb" + - "w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", "AQAB", "RS256", - null, null, null); - JwtOptionsConfig options = new JwtOptionsConfig( - "https://auth.example.com", - "https://api.example.com", - asList(key0, key1), - Duration.ofSeconds(30)); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .issuer("https://auth.example.com") + .audience("https://api.example.com") + .key() + .kty("EC") + .kid("1") + .use("enc") + .crv("P-256") + .x("MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4") + .y("4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM") + .build() + .key() + .kty("RSA") + .kid("2011-04-29") + .n("0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx" + + "4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs" + + "tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2" + + "QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI" + + "SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb" + + "w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw") + .e("AQAB") + .alg("RS256") + .build() + .challenge(Duration.ofSeconds(30)) + .build(); String text = jsonb.toJson(options); diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/keys/JwtKeyConfigs.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/keys/JwtKeyConfigs.java index 53b45b3dff..8fcce6ece3 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/keys/JwtKeyConfigs.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/keys/JwtKeyConfigs.java @@ -14,7 +14,7 @@ */ package io.aklivity.zilla.runtime.guard.jwt.internal.keys; -import io.aklivity.zilla.runtime.guard.jwt.internal.config.JwtKeyConfig; +import io.aklivity.zilla.runtime.guard.jwt.config.JwtKeyConfig; public final class JwtKeyConfigs { @@ -24,33 +24,29 @@ public final class JwtKeyConfigs static { // RFC 7515, section A.2.1 - RFC7515_RS256_CONFIG = new JwtKeyConfig( - "RSA", - "test", - "verify", - "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx" + - "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs" + - "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH" + - "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV" + - "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8" + - "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", - "AQAB", - "RS256", - null, - null, - null); + RFC7515_RS256_CONFIG = JwtKeyConfig.builder() + .kty("RSA") + .kid("test") + .use("verify") + .n("ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx" + + "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs" + + "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH" + + "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV" + + "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8" + + "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ") + .e("AQAB") + .alg("RS256") + .build(); // RFC 7515, section A.3.1 - RFC7515_ES256_CONFIG = new JwtKeyConfig( - "RSA", - "test", - "verify", - null, - null, - null, - "P-256", - "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", - "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"); + RFC7515_ES256_CONFIG = JwtKeyConfig.builder() + .kty("RSA") + .kid("test") + .use("verify") + .crv("P-256") + .x("f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU") + .y("x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0") + .build(); } private JwtKeyConfigs() diff --git a/runtime/metrics-grpc/pom.xml b/runtime/metrics-grpc/pom.xml index 02ba791a78..0e3bae4fa6 100644 --- a/runtime/metrics-grpc/pom.xml +++ b/runtime/metrics-grpc/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/metrics-http/pom.xml b/runtime/metrics-http/pom.xml index ca20215860..d35fa39af7 100644 --- a/runtime/metrics-http/pom.xml +++ b/runtime/metrics-http/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/metrics-stream/pom.xml b/runtime/metrics-stream/pom.xml index 7267ac8227..f263d4014c 100644 --- a/runtime/metrics-stream/pom.xml +++ b/runtime/metrics-stream/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/pom.xml b/runtime/pom.xml index 9a9fd3492b..47920a8e6c 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla zilla - 0.9.51 + 0.9.52 ../pom.xml @@ -28,6 +28,8 @@ binding-http-kafka binding-kafka binding-kafka-grpc + binding-mqtt + binding-mqtt-kafka binding-proxy binding-sse binding-sse-kafka @@ -103,6 +105,16 @@ binding-kafka ${project.version} + + ${project.groupId} + binding-mqtt + ${project.version} + + + ${project.groupId} + binding-mqtt-kafka + ${project.version} + ${project.groupId} binding-proxy diff --git a/runtime/vault-filesystem/pom.xml b/runtime/vault-filesystem/pom.xml index b5a20a9e86..f521404d5d 100644 --- a/runtime/vault-filesystem/pom.xml +++ b/runtime/vault-filesystem/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla runtime - 0.9.51 + 0.9.52 ../pom.xml diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemOptionsConfig.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemOptionsConfig.java new file mode 100644 index 0000000000..e124c1ec23 --- /dev/null +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemOptionsConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.vault.filesystem.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class FileSystemOptionsConfig extends OptionsConfig +{ + public final FileSystemStoreConfig keys; + public final FileSystemStoreConfig trust; + public final FileSystemStoreConfig signers; + + public static FileSystemOptionsConfigBuilder builder() + { + return new FileSystemOptionsConfigBuilder<>(FileSystemOptionsConfig.class::cast); + } + + public static FileSystemOptionsConfigBuilder builder( + Function mapper) + { + return new FileSystemOptionsConfigBuilder<>(mapper); + } + + FileSystemOptionsConfig( + FileSystemStoreConfig keys, + FileSystemStoreConfig trust, + FileSystemStoreConfig signers) + { + this.keys = keys; + this.trust = trust; + this.signers = signers; + } +} diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemOptionsConfigBuilder.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemOptionsConfigBuilder.java new file mode 100644 index 0000000000..124f2ed957 --- /dev/null +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemOptionsConfigBuilder.java @@ -0,0 +1,85 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.vault.filesystem.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; +import io.aklivity.zilla.runtime.engine.config.OptionsConfig; + +public final class FileSystemOptionsConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private FileSystemStoreConfig keys; + private FileSystemStoreConfig trust; + private FileSystemStoreConfig signers; + + FileSystemOptionsConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public FileSystemStoreConfigBuilder> keys() + { + return new FileSystemStoreConfigBuilder<>(this::keys); + } + + public FileSystemStoreConfigBuilder> trust() + { + return new FileSystemStoreConfigBuilder<>(this::trust); + } + + public FileSystemStoreConfigBuilder> signers() + { + return new FileSystemStoreConfigBuilder<>(this::signers); + } + + public FileSystemOptionsConfigBuilder keys( + FileSystemStoreConfig keys) + { + this.keys = keys; + return this; + } + + public FileSystemOptionsConfigBuilder trust( + FileSystemStoreConfig trust) + { + this.trust = trust; + return this; + } + + public FileSystemOptionsConfigBuilder signers( + FileSystemStoreConfig signers) + { + this.signers = signers; + return this; + } + + @Override + public T build() + { + return mapper.apply(new FileSystemOptionsConfig(keys, trust, signers)); + } +} diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemStoreConfig.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemStoreConfig.java new file mode 100644 index 0000000000..3630dbb331 --- /dev/null +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemStoreConfig.java @@ -0,0 +1,40 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.vault.filesystem.config; + +import static java.util.function.Function.identity; + +public final class FileSystemStoreConfig +{ + public final String store; + public final String type; + public final String password; + + public static FileSystemStoreConfigBuilder builder() + { + return new FileSystemStoreConfigBuilder<>(identity()); + } + + FileSystemStoreConfig( + String store, + String type, + String password) + { + this.store = store; + this.type = type; + this.password = password; + } +} diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemStoreConfigBuilder.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemStoreConfigBuilder.java new file mode 100644 index 0000000000..8ab4fe671c --- /dev/null +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/config/FileSystemStoreConfigBuilder.java @@ -0,0 +1,69 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.vault.filesystem.config; + +import java.util.function.Function; + +import io.aklivity.zilla.runtime.engine.config.ConfigBuilder; + +public final class FileSystemStoreConfigBuilder extends ConfigBuilder> +{ + private final Function mapper; + + private String store; + private String type; + private String password; + + FileSystemStoreConfigBuilder( + Function mapper) + { + this.mapper = mapper; + } + + @Override + @SuppressWarnings("unchecked") + protected Class> thisType() + { + return (Class>) getClass(); + } + + public FileSystemStoreConfigBuilder store( + String store) + { + this.store = store; + return this; + } + + public FileSystemStoreConfigBuilder type( + String type) + { + this.type = type; + return this; + } + + public FileSystemStoreConfigBuilder password( + String password) + { + this.password = password; + return this; + } + + @Override + public T build() + { + return mapper.apply(new FileSystemStoreConfig(store, type, password)); + } +} diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemContext.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemContext.java index d98e32d6e3..0b303d4bc6 100644 --- a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemContext.java +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemContext.java @@ -22,7 +22,7 @@ import io.aklivity.zilla.runtime.engine.EngineContext; import io.aklivity.zilla.runtime.engine.config.VaultConfig; import io.aklivity.zilla.runtime.engine.vault.VaultContext; -import io.aklivity.zilla.runtime.vault.filesystem.internal.config.FileSystemOptionsConfig; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; final class FileSystemContext implements VaultContext { diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultHandler.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultHandler.java index dc3ee231c0..c465063d99 100644 --- a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultHandler.java +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultHandler.java @@ -36,8 +36,8 @@ import org.agrona.LangUtil; import io.aklivity.zilla.runtime.engine.vault.VaultHandler; -import io.aklivity.zilla.runtime.vault.filesystem.internal.config.FileSystemOptionsConfig; -import io.aklivity.zilla.runtime.vault.filesystem.internal.config.FileSystemStore; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemStoreConfig; public class FileSystemVaultHandler implements VaultHandler { @@ -95,21 +95,21 @@ public PrivateKeyEntry[] keys( private static Function supplyLookupPrivateKeyEntry( Function resolvePath, - FileSystemStore aliases) + FileSystemStoreConfig aliases) { return supplyLookupAlias(resolvePath, aliases, FileSystemVaultHandler::lookupPrivateKeyEntry); } private static Function supplyLookupTrustedCertificateEntry( Function resolvePath, - FileSystemStore aliases) + FileSystemStoreConfig aliases) { return supplyLookupAlias(resolvePath, aliases, FileSystemVaultHandler::lookupTrustedCertificateEntry); } private Function, KeyStore.PrivateKeyEntry[]> supplyLookupPrivateKeyEntries( Function resolvePath, - FileSystemStore entries) + FileSystemStoreConfig entries) { Function, KeyStore.PrivateKeyEntry[]> lookupKeys = p -> null; @@ -166,7 +166,7 @@ private Function, KeyStore.PrivateKeyEntry[]> supplyLoo private static Function supplyLookupAlias( Function resolvePath, - FileSystemStore aliases, + FileSystemStoreConfig aliases, Lookup lookup) { Function lookupAlias = a -> null; diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfig.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfig.java deleted file mode 100644 index 23a75d231f..0000000000 --- a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.vault.filesystem.internal.config; - -import io.aklivity.zilla.runtime.engine.config.OptionsConfig; - -public class FileSystemOptionsConfig extends OptionsConfig -{ - public final FileSystemStore keys; - public final FileSystemStore trust; - public final FileSystemStore signers; - - public FileSystemOptionsConfig( - FileSystemStore keys, - FileSystemStore trust, - FileSystemStore signers) - { - this.keys = keys; - this.trust = trust; - this.signers = signers; - } -} diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapter.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapter.java index 6e7f1dd889..c73a3a69e1 100644 --- a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapter.java +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapter.java @@ -22,6 +22,8 @@ import io.aklivity.zilla.runtime.engine.config.OptionsConfig; import io.aklivity.zilla.runtime.engine.config.OptionsConfigAdapterSpi; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfigBuilder; import io.aklivity.zilla.runtime.vault.filesystem.internal.FileSystemVault; public final class FileSystemOptionsConfigAdapter implements OptionsConfigAdapterSpi, JsonbAdapter @@ -30,7 +32,7 @@ public final class FileSystemOptionsConfigAdapter implements OptionsConfigAdapte private static final String TRUST_NAME = "trust"; private static final String SIGNERS_NAME = "signers"; - private final FileSystemStoreAdapter store = new FileSystemStoreAdapter(); + private final FileSystemStoreConfigAdapter store = new FileSystemStoreConfigAdapter(); @Override public String type() @@ -74,16 +76,23 @@ public JsonObject adaptToJson( public OptionsConfig adaptFromJson( JsonObject object) { - FileSystemStore keys = object.containsKey(KEYS_NAME) - ? store.adaptFromJson(object.getJsonObject(KEYS_NAME)) - : null; - FileSystemStore trust = object.containsKey(TRUST_NAME) - ? store.adaptFromJson(object.getJsonObject(TRUST_NAME)) - : null; - FileSystemStore signers = object.containsKey(SIGNERS_NAME) - ? store.adaptFromJson(object.getJsonObject(SIGNERS_NAME)) - : null; - - return new FileSystemOptionsConfig(keys, trust, signers); + FileSystemOptionsConfigBuilder fsOptions = FileSystemOptionsConfig.builder(); + + if (object.containsKey(KEYS_NAME)) + { + fsOptions.keys(store.adaptFromJson(object.getJsonObject(KEYS_NAME))); + } + + if (object.containsKey(TRUST_NAME)) + { + fsOptions.trust(store.adaptFromJson(object.getJsonObject(TRUST_NAME))); + } + + if (object.containsKey(SIGNERS_NAME)) + { + fsOptions.signers(store.adaptFromJson(object.getJsonObject(SIGNERS_NAME))); + } + + return fsOptions.build(); } } diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStore.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStore.java deleted file mode 100644 index 3e9e61031c..0000000000 --- a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStore.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.vault.filesystem.internal.config; - -public class FileSystemStore -{ - public final String store; - public final String type; - public final String password; - - public FileSystemStore( - String store, - String type, - String password) - { - this.store = store; - this.type = type; - this.password = password; - } -} diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStoreAdapter.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStoreAdapter.java deleted file mode 100644 index e3b128a2ad..0000000000 --- a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStoreAdapter.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2021-2023 Aklivity Inc. - * - * Aklivity licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.aklivity.zilla.runtime.vault.filesystem.internal.config; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.bind.adapter.JsonbAdapter; - -public final class FileSystemStoreAdapter implements JsonbAdapter -{ - private static final String STORE_NAME = "store"; - private static final String TYPE_NAME = "type"; - private static final String PASSWORD_NAME = "password"; - - @Override - public JsonObject adaptToJson( - FileSystemStore store) - { - JsonObjectBuilder object = Json.createObjectBuilder(); - - object.add(STORE_NAME, store.store); - - if (store.type != null) - { - object.add(TYPE_NAME, store.type); - } - - if (store.password != null) - { - object.add(PASSWORD_NAME, store.password); - } - - return object.build(); - } - - @Override - public FileSystemStore adaptFromJson( - JsonObject object) - { - String store = object.getString(STORE_NAME); - String type = object.containsKey(TYPE_NAME) ? object.getString(TYPE_NAME) : null; - String password = object.containsKey(PASSWORD_NAME) ? object.getString(PASSWORD_NAME) : null; - - return new FileSystemStore(store, type, password); - } -} diff --git a/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStoreConfigAdapter.java b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStoreConfigAdapter.java new file mode 100644 index 0000000000..ed66c57afc --- /dev/null +++ b/runtime/vault-filesystem/src/main/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemStoreConfigAdapter.java @@ -0,0 +1,72 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.runtime.vault.filesystem.internal.config; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.bind.adapter.JsonbAdapter; + +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemStoreConfig; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemStoreConfigBuilder; + +public final class FileSystemStoreConfigAdapter implements JsonbAdapter +{ + private static final String STORE_NAME = "store"; + private static final String TYPE_NAME = "type"; + private static final String PASSWORD_NAME = "password"; + + @Override + public JsonObject adaptToJson( + FileSystemStoreConfig store) + { + JsonObjectBuilder object = Json.createObjectBuilder(); + + object.add(STORE_NAME, store.store); + + if (store.type != null) + { + object.add(TYPE_NAME, store.type); + } + + if (store.password != null) + { + object.add(PASSWORD_NAME, store.password); + } + + return object.build(); + } + + @Override + public FileSystemStoreConfig adaptFromJson( + JsonObject object) + { + FileSystemStoreConfigBuilder fsStore = FileSystemStoreConfig.builder() + .store(object.getString(STORE_NAME)); + + if (object.containsKey(TYPE_NAME)) + { + fsStore.type(object.getString(TYPE_NAME)); + } + + if (object.containsKey(PASSWORD_NAME)) + { + fsStore.password(object.getString(PASSWORD_NAME)); + } + + return fsStore.build(); + } +} diff --git a/runtime/vault-filesystem/src/main/moditect/module-info.java b/runtime/vault-filesystem/src/main/moditect/module-info.java index 844c5aacb2..144ea41705 100644 --- a/runtime/vault-filesystem/src/main/moditect/module-info.java +++ b/runtime/vault-filesystem/src/main/moditect/module-info.java @@ -17,6 +17,8 @@ { requires io.aklivity.zilla.runtime.engine; + exports io.aklivity.zilla.runtime.vault.filesystem.config; + provides io.aklivity.zilla.runtime.engine.vault.VaultFactorySpi with io.aklivity.zilla.runtime.vault.filesystem.internal.FileSystemVaultFactorySpi; diff --git a/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultIT.java b/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultIT.java index 2987b14a29..55ebfa788f 100644 --- a/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultIT.java +++ b/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultIT.java @@ -34,9 +34,7 @@ public class FileSystemVaultIT private final EngineRule engine = new EngineRule() .directory("target/zilla-itests") - .commandBufferCapacity(1024) - .responseBufferCapacity(1024) - .counterValuesBufferCapacity(8192) + .countersBufferCapacity(8192) .configurationRoot("io/aklivity/zilla/specs/vault/filesystem/config") .configure(ENGINE_DRAIN_ON_CLOSE, false) .clean(); diff --git a/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultTest.java b/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultTest.java index e68ff68730..fecdd376f6 100644 --- a/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultTest.java +++ b/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/FileSystemVaultTest.java @@ -25,17 +25,25 @@ import org.junit.Test; -import io.aklivity.zilla.runtime.vault.filesystem.internal.config.FileSystemOptionsConfig; -import io.aklivity.zilla.runtime.vault.filesystem.internal.config.FileSystemStore; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; public class FileSystemVaultTest { @Test public void shouldResolveServer() throws Exception { - FileSystemStore keys = new FileSystemStore("stores/server/keys", "pkcs12", "generated"); - FileSystemStore trust = new FileSystemStore("stores/server/trust", "pkcs12", "generated"); - FileSystemOptionsConfig options = new FileSystemOptionsConfig(keys, trust, null); + FileSystemOptionsConfig options = FileSystemOptionsConfig.builder() + .keys() + .store("stores/server/keys") + .type("pkcs12") + .password("generated") + .build() + .trust() + .store("stores/server/trust") + .type("pkcs12") + .password("generated") + .build() + .build(); FileSystemVaultHandler vault = new FileSystemVaultHandler(options, FileSystemVaultTest.class::getResource); @@ -49,9 +57,18 @@ public void shouldResolveServer() throws Exception @Test public void shouldResolveClient() throws Exception { - FileSystemStore keys = new FileSystemStore("stores/client/keys", "pkcs12", "generated"); - FileSystemStore signers = new FileSystemStore("stores/server/trust", "pkcs12", "generated"); - FileSystemOptionsConfig options = new FileSystemOptionsConfig(keys, null, signers); + FileSystemOptionsConfig options = FileSystemOptionsConfig.builder() + .keys() + .store("stores/client/keys") + .type("pkcs12") + .password("generated") + .build() + .signers() + .store("stores/server/trust") + .type("pkcs12") + .password("generated") + .build() + .build(); FileSystemVaultHandler vault = new FileSystemVaultHandler(options, FileSystemVaultTest.class::getResource); diff --git a/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java b/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java index 3e228d1efb..fda79b60bf 100644 --- a/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java +++ b/runtime/vault-filesystem/src/test/java/io/aklivity/zilla/runtime/vault/filesystem/internal/config/FileSystemOptionsConfigAdapterTest.java @@ -15,6 +15,7 @@ */ package io.aklivity.zilla.runtime.vault.filesystem.internal.config; +import static java.util.function.Function.identity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -27,6 +28,9 @@ import org.junit.Before; import org.junit.Test; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemOptionsConfig; +import io.aklivity.zilla.runtime.vault.filesystem.config.FileSystemStoreConfig; + public class FileSystemOptionsConfigAdapterTest { private Jsonb jsonb; @@ -49,7 +53,7 @@ public void shouldReadOptions() FileSystemOptionsConfig options = jsonb.fromJson(text, FileSystemOptionsConfig.class); assertThat(options, not(nullValue())); - assertThat(options.keys, nullValue(FileSystemStore.class)); + assertThat(options.keys, nullValue(FileSystemStoreConfig.class)); } @Test @@ -77,7 +81,8 @@ public void shouldReadOptionsWithKeys() @Test public void shouldWriteOptions() { - FileSystemOptionsConfig options = new FileSystemOptionsConfig(null, null, null); + FileSystemOptionsConfig options = FileSystemOptionsConfig.builder() + .build(); String text = jsonb.toJson(options); @@ -88,8 +93,15 @@ public void shouldWriteOptions() @Test public void shouldWriteOptionsWithKeys() { - FileSystemStore keys = new FileSystemStore("localhost.p12", "pkcs12", "generated"); - FileSystemOptionsConfig options = new FileSystemOptionsConfig(keys, null, null); + FileSystemOptionsConfig options = FileSystemOptionsConfig.builder() + .inject(identity()) + .keys() + .inject(identity()) + .store("localhost.p12") + .type("pkcs12") + .password("generated") + .build() + .build(); String text = jsonb.toJson(options); diff --git a/specs/binding-echo.spec/pom.xml b/specs/binding-echo.spec/pom.xml index b61fcc6392..267325672f 100644 --- a/specs/binding-echo.spec/pom.xml +++ b/specs/binding-echo.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-fan.spec/pom.xml b/specs/binding-fan.spec/pom.xml index 84ada8bf2c..66184d02f9 100644 --- a/specs/binding-fan.spec/pom.xml +++ b/specs/binding-fan.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-filesystem.spec/pom.xml b/specs/binding-filesystem.spec/pom.xml index 667adaf50f..89aec467f2 100644 --- a/specs/binding-filesystem.spec/pom.xml +++ b/specs/binding-filesystem.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-grpc-kafka.spec/pom.xml b/specs/binding-grpc-kafka.spec/pom.xml index bf46e6ceba..a673e26c5d 100644 --- a/specs/binding-grpc-kafka.spec/pom.xml +++ b/specs/binding-grpc-kafka.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/client.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/client.rpt index e57f947461..9e463519a3 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/client.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/client.rpt @@ -134,6 +134,7 @@ read ${grpc:protobuf() read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/server.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/server.rpt index 67c95b6b5d..689d60bb74 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/server.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/bidi.stream.rpc/server.rpt @@ -132,6 +132,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/client.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/client.rpt index 9b14d76b8b..70238172e0 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/client.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/client.rpt @@ -131,6 +131,7 @@ read zilla:data.null read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/server.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/server.rpt index b5fcc11706..20a82598b7 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/server.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/client.stream.rpc/server.rpt @@ -130,6 +130,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/client.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/client.rpt index f9f4c96f5b..7924467f0b 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/client.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/client.rpt @@ -115,6 +115,7 @@ read ${grpc:protobuf() read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/server.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/server.rpt index 06f67ddf4c..4de87c778e 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/server.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/server.stream.rpc/server.rpt @@ -115,6 +115,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/client.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/client.rpt index 3267fdb0c9..7ce3c0b948 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/client.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/client.rpt @@ -113,6 +113,7 @@ read zilla:data.null read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/server.rpt b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/server.rpt index 07b295000f..f847566d05 100644 --- a/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/server.rpt +++ b/specs/binding-grpc-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/grpc/kafka/streams/kafka/produce/unary.rpc/server.rpt @@ -114,6 +114,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-grpc.spec/pom.xml b/specs/binding-grpc.spec/pom.xml index 43fba06d98..e0d1c00510 100644 --- a/specs/binding-grpc.spec/pom.xml +++ b/specs/binding-grpc.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-http-filesystem.spec/pom.xml b/specs/binding-http-filesystem.spec/pom.xml index c60dea7736..45cfd0eb3d 100644 --- a/specs/binding-http-filesystem.spec/pom.xml +++ b/specs/binding-http-filesystem.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-http-kafka.spec/pom.xml b/specs/binding-http-kafka.spec/pom.xml index 9a3b417dec..aa10040a0e 100644 --- a/specs/binding-http-kafka.spec/pom.xml +++ b/specs/binding-http-kafka.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/client.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/client.rpt index f731d79b04..1bc6584da2 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/client.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/client.rpt @@ -51,6 +51,7 @@ read '{ "name": "widget" }' read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/server.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/server.rpt index dd908087ae..9dd9f5881c 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/server.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.modified/server.rpt @@ -55,6 +55,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/client.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/client.rpt index b3dae39e06..82283db856 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/client.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/client.rpt @@ -50,6 +50,7 @@ read '{ "name": "widget" }' read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/server.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/server.rpt index 382be07ace..39541da663 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/server.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.item.no.etag.modified/server.rpt @@ -54,6 +54,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/client.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/client.rpt index a798987ec5..c8b4ac2fde 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/client.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/client.rpt @@ -70,6 +70,7 @@ read '{ "name": "gizmo" }' read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .progress(1, 1, 1, 1) .build() diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/server.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/server.rpt index 2930ecee42..565fe37115 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/server.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.modified/server.rpt @@ -76,6 +76,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .progress(1, 1, 1, 1) .build() diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/client.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/client.rpt index 520e43e31b..55da055eb3 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/client.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/client.rpt @@ -73,6 +73,7 @@ read '{ "name": "gizmo" }' read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 1, 1, 1) .progress(1, 1, 1, 1) .build() diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/server.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/server.rpt index 9a6aeebc37..34e925d118 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/server.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items.write.flush/server.rpt @@ -79,6 +79,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 1, 1, 1) .progress(1, 1, 1, 1) .build() diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/client.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/client.rpt index 257a5d614d..7b75e00edc 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/client.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/client.rpt @@ -71,6 +71,7 @@ read '{ "name": "gizmo" }' read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 1, 1, 1) .progress(1, 1, 1, 1) .build() diff --git a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/server.rpt b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/server.rpt index 9b30da2f32..1591d0a2da 100644 --- a/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/server.rpt +++ b/specs/binding-http-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/http/kafka/streams/kafka/get.items/server.rpt @@ -77,6 +77,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 1, 1, 1) .progress(1, 1, 1, 1) .build() diff --git a/specs/binding-http.spec/pom.xml b/specs/binding-http.spec/pom.xml index 25ba2fe102..51d7c72457 100644 --- a/specs/binding-http.spec/pom.xml +++ b/specs/binding-http.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-kafka-grpc.spec/pom.xml b/specs/binding-kafka-grpc.spec/pom.xml index 1038dd2afc..7398f03305 100644 --- a/specs/binding-kafka-grpc.spec/pom.xml +++ b/specs/binding-kafka-grpc.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-kafka.spec/pom.xml b/specs/binding-kafka.spec/pom.xml index e641f4e41d..7b8d82ad62 100644 --- a/specs/binding-kafka.spec/pom.xml +++ b/specs/binding-kafka.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java b/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java index 851c7e7f3b..0a3791c485 100644 --- a/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java +++ b/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java @@ -25,6 +25,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.function.Predicate; + import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; @@ -59,9 +60,15 @@ import io.aklivity.zilla.specs.binding.kafka.internal.types.OctetsFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.String16FW; import io.aklivity.zilla.specs.binding.kafka.internal.types.String8FW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.rebalance.ConsumerAssignmentFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.rebalance.MemberAssignmentFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.rebalance.TopicAssignmentFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaApi; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaBootstrapBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaConsumerAssignmentFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaConsumerBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaConsumerDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaDescribeBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaDescribeDataExFW; @@ -70,16 +77,26 @@ import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaFetchFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupBeginExFW; -import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupFlushExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupMemberFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupMemberMetadataFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupTopicMetadataFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedConsumerFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedFetchFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMetaBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMetaDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetCommitBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetCommitDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetFetchBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetFetchDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaProduceBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaProduceDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaProduceFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaTopicPartitionFW; public final class KafkaFunctions { @@ -269,6 +286,24 @@ public static byte[] varint( } } + @Function + public static KafkaGroupMemberMetadataBuilder memberMetadata() + { + return new KafkaGroupMemberMetadataBuilder(); + } + + @Function + public static KafkaMemberAssignmentsBuilder memberAssignment() + { + return new KafkaMemberAssignmentsBuilder(); + } + + @Function + public static KafkaTopicAssignmentsBuilder topicAssignment() + { + return new KafkaTopicAssignmentsBuilder(); + } + public abstract static class KafkaHeadersBuilder { private final KafkaHeadersFW.Builder headersRW = new KafkaHeadersFW.Builder(); @@ -548,6 +583,305 @@ private void set( } } + public static final class KafkaGroupMemberMetadataBuilder + { + private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final KafkaGroupMemberMetadataFW.Builder groupMemberMetadataRW = + new KafkaGroupMemberMetadataFW.Builder(); + + public KafkaGroupMemberMetadataBuilder() + { + groupMemberMetadataRW.wrap(writeBuffer, 0, writeBuffer.capacity()); + } + + public KafkaGroupMemberMetadataBuilder consumerId( + String consumerId) + { + groupMemberMetadataRW.consumerId(consumerId); + return this; + } + + public KafkaTopicsBuilder topic( + String topic) + { + KafkaTopicsBuilder topicsBuilder = new KafkaTopicsBuilder(topic); + return topicsBuilder; + } + + public byte[] build() + { + final KafkaGroupMemberMetadataFW metadata = groupMemberMetadataRW.build(); + final byte[] array = new byte[metadata.sizeof()]; + metadata.buffer().getBytes(metadata.offset(), array); + return array; + } + + class KafkaTopicsBuilder + { + private final MutableDirectBuffer topicBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final KafkaGroupTopicMetadataFW.Builder topicsRW = new KafkaGroupTopicMetadataFW.Builder(); + + KafkaTopicsBuilder( + String topic) + { + topicsRW.wrap(topicBuffer, 0, topicBuffer.capacity()); + topicsRW.topic(topic); + } + + public KafkaTopicsBuilder partitionId( + int partitionId) + { + topicsRW.partitionsItem(i -> i.partitionId(partitionId)); + return this; + } + + public KafkaGroupMemberMetadataBuilder build() + { + KafkaGroupTopicMetadataFW topic = topicsRW.build(); + groupMemberMetadataRW.topicsItem(i -> i.topic(topic.topic()).partitions(topic.partitions())); + + return KafkaGroupMemberMetadataBuilder.this; + } + } + } + + public static final class KafkaMemberAssignmentsBuilder + { + private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + + private final Array32FW.Builder memberAssignmentsRW = + new Array32FW.Builder(new MemberAssignmentFW.Builder(), new MemberAssignmentFW()); + + public KafkaMemberAssignmentsBuilder() + { + memberAssignmentsRW.wrap(writeBuffer, 0, writeBuffer.capacity()); + } + + public KafkaMemberBuilder member( + String memberId) + { + KafkaMemberBuilder member = new KafkaMemberBuilder(memberId); + return member; + } + + public byte[] build() + { + Array32FW members = memberAssignmentsRW.build(); + final byte[] array = new byte[members.sizeof()]; + members.buffer().getBytes(members.offset(), array); + return array; + } + + class KafkaMemberBuilder + { + private final MutableDirectBuffer memberBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final MemberAssignmentFW.Builder assignmentRW = new MemberAssignmentFW.Builder(); + private final MutableDirectBuffer topicAssignmentBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final Array32FW.Builder topicAssignmentsRW = + new Array32FW.Builder(new TopicAssignmentFW.Builder(), new TopicAssignmentFW()); + + KafkaMemberBuilder( + String memberId) + { + assignmentRW.wrap(memberBuffer, 0, memberBuffer.capacity()) + .memberId(memberId); + topicAssignmentsRW.wrap(topicAssignmentBuffer, 0, topicAssignmentBuffer.capacity()); + } + + public KafkaTopicAssignmentBuilder assignment() + { + KafkaTopicAssignmentBuilder assignment = new KafkaTopicAssignmentBuilder(); + return assignment; + } + + public KafkaMemberAssignmentsBuilder build() + { + Array32FW topicAssignments = topicAssignmentsRW.build(); + assignmentRW.assignments(topicAssignments); + MemberAssignmentFW assignment = assignmentRW.build(); + memberAssignmentsRW.item(m -> m.set(assignment)); + + return KafkaMemberAssignmentsBuilder.this; + } + + class KafkaTopicAssignmentBuilder + { + private final MutableDirectBuffer assignmentBuffer = new UnsafeBuffer(new byte[1024 * 8]); + TopicAssignmentFW.Builder assignmentRW = new TopicAssignmentFW.Builder(); + + KafkaTopicAssignmentBuilder() + { + assignmentRW.wrap(assignmentBuffer, 0, assignmentBuffer.capacity()); + } + + public KafkaTopicAssignmentBuilder topic( + String topic) + { + assignmentRW.topic(topic); + return this; + } + + public KafkaTopicAssignmentBuilder partitionId( + int partitionId) + { + assignmentRW.partitionsItem(p -> p.partitionId(partitionId)); + return this; + } + + public KafkaConsumerBuilder consumer() + { + KafkaConsumerBuilder consumerBuilder = new KafkaConsumerBuilder(); + return consumerBuilder; + } + + public KafkaMemberBuilder build() + { + TopicAssignmentFW assignment = assignmentRW.build(); + topicAssignmentsRW.item(i -> i + .topic(assignment.topic()) + .partitions(assignment.partitions()) + .userdata(assignment.userdata())); + return KafkaMemberBuilder.this; + } + + class KafkaConsumerBuilder + { + private final MutableDirectBuffer consumerBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final ConsumerAssignmentFW.Builder consumerRW = new ConsumerAssignmentFW.Builder(); + KafkaConsumerBuilder() + { + consumerRW.wrap(consumerBuffer, 0, consumerBuffer.capacity()); + } + + public KafkaConsumerBuilder id( + String id) + { + consumerRW.consumerId(id); + return this; + } + + public KafkaConsumerBuilder partitionId( + int partitionId) + { + consumerRW.partitionsItem(p -> p.partitionId(partitionId)); + return this; + } + + public KafkaTopicAssignmentBuilder build() + { + ConsumerAssignmentFW consumer = consumerRW.build(); + assignmentRW.userdataItem(u -> u + .consumerId(consumer.consumerId()) + .partitions(consumer.partitions())); + + return KafkaTopicAssignmentBuilder.this; + } + } + } + } + } + + public static final class KafkaTopicAssignmentsBuilder + { + private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + + private final Array32FW.Builder topicAssignments = + new Array32FW.Builder(new TopicAssignmentFW.Builder(), new TopicAssignmentFW()); + + public KafkaTopicAssignmentsBuilder() + { + topicAssignments.wrap(writeBuffer, 0, writeBuffer.capacity()); + } + + public KafkaTopicBuilder topic() + { + KafkaTopicBuilder kafkaTopicBuilder = new KafkaTopicBuilder(); + return kafkaTopicBuilder; + } + + public byte[] build() + { + Array32FW topics = topicAssignments.build(); + final byte[] array = new byte[topics.sizeof()]; + topics.buffer().getBytes(topics.offset(), array); + return array; + } + + class KafkaTopicBuilder + { + private final MutableDirectBuffer topicBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final TopicAssignmentFW.Builder topicAssignmentRW = new TopicAssignmentFW.Builder(); + KafkaTopicBuilder() + { + topicAssignmentRW.wrap(topicBuffer, 0, topicBuffer.capacity()); + } + + public KafkaTopicBuilder id( + String topic) + { + topicAssignmentRW.topic(topic); + return this; + } + + public KafkaTopicBuilder partitionId( + int partitionId) + { + topicAssignmentRW.partitionsItem(p -> p.partitionId(partitionId)); + return this; + } + + public KafkaConsumerBuilder consumer() + { + KafkaConsumerBuilder consumerBuilder = new KafkaConsumerBuilder(); + return consumerBuilder; + } + + public KafkaTopicAssignmentsBuilder build() + { + TopicAssignmentFW topicAssignment = topicAssignmentRW.build(); + topicAssignments.item(i -> i + .topic(topicAssignment.topic()) + .partitions(topicAssignment.partitions()) + .userdata(topicAssignment.userdata())); + return KafkaTopicAssignmentsBuilder.this; + } + + class KafkaConsumerBuilder + { + private final MutableDirectBuffer consumerBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final ConsumerAssignmentFW.Builder consumerRW = new ConsumerAssignmentFW.Builder(); + KafkaConsumerBuilder() + { + consumerRW.wrap(consumerBuffer, 0, consumerBuffer.capacity()); + } + + public KafkaConsumerBuilder id( + String id) + { + consumerRW.consumerId(id); + return this; + } + + public KafkaConsumerBuilder partitionId( + int partitionId) + { + consumerRW.partitionsItem(p -> p.partitionId(partitionId)); + return this; + } + + public KafkaTopicBuilder build() + { + ConsumerAssignmentFW consumer = consumerRW.build(); + topicAssignmentRW.userdataItem(u -> u + .consumerId(consumer.consumerId()) + .partitions(consumer.partitions())); + + return KafkaTopicBuilder.this; + } + } + } + } + public static final class KafkaBeginExBuilder { private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); @@ -617,6 +951,27 @@ public KafkaGroupBeginExBuilder group() return new KafkaGroupBeginExBuilder(); } + public KafkaConsumerBeginExBuilder consumer() + { + beginExRW.kind(KafkaApi.CONSUMER.value()); + + return new KafkaConsumerBeginExBuilder(); + } + + public KafkaOffsetFetchBeginExBuilder offsetFetch() + { + beginExRW.kind(KafkaApi.OFFSET_FETCH.value()); + + return new KafkaOffsetFetchBeginExBuilder(); + } + + public KafkaOffsetCommitBeginExBuilder offsetCommit() + { + beginExRW.kind(KafkaApi.OFFSET_COMMIT.value()); + + return new KafkaOffsetCommitBeginExBuilder(); + } + public byte[] build() { final KafkaBeginExFW beginEx = beginExRO; @@ -672,6 +1027,27 @@ public KafkaMergedBeginExBuilder topic( return this; } + public KafkaMergedBeginExBuilder groupId( + String groupId) + { + mergedBeginExRW.groupId(groupId); + return this; + } + + public KafkaMergedBeginExBuilder consumerId( + String consumerId) + { + mergedBeginExRW.consumerId(consumerId); + return this; + } + + public KafkaMergedBeginExBuilder timeout( + int timeout) + { + mergedBeginExRW.timeout(timeout); + return this; + } + public KafkaMergedBeginExBuilder partition( int partitionId, long offset) @@ -1006,6 +1382,13 @@ public KafkaGroupBeginExBuilder timeout( return this; } + public KafkaGroupBeginExBuilder metadata( + byte[] metadata) + { + groupBeginExRW.metadataLen(metadata.length).metadata(m -> m.set(metadata)); + return this; + } + public KafkaBeginExBuilder build() { final KafkaGroupBeginExFW groupBeginEx = groupBeginExRW.build(); @@ -1013,55 +1396,180 @@ public KafkaBeginExBuilder build() return KafkaBeginExBuilder.this; } } - } - public static final class KafkaDataExBuilder - { - private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + public final class KafkaConsumerBeginExBuilder + { + private final KafkaConsumerBeginExFW.Builder consumerBeginExRW = new KafkaConsumerBeginExFW.Builder(); + private final MutableDirectBuffer partitionBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final Array32FW.Builder partitionsRW = + new Array32FW.Builder<>(new KafkaTopicPartitionFW.Builder(), new KafkaTopicPartitionFW()); - private final KafkaDataExFW dataExRO = new KafkaDataExFW(); - private final KafkaDataExFW.Builder dataExRW = new KafkaDataExFW.Builder(); + private KafkaConsumerBeginExBuilder() + { + consumerBeginExRW.wrap(writeBuffer, KafkaBeginExFW.FIELD_OFFSET_CONSUMER, writeBuffer.capacity()); + partitionsRW.wrap(partitionBuffer, 0, partitionBuffer.capacity()); + } - private KafkaDataExBuilder() - { - dataExRW.wrap(writeBuffer, 0, writeBuffer.capacity()); - } + public KafkaConsumerBeginExBuilder groupId( + String groupId) + { + consumerBeginExRW.groupId(groupId); + return this; + } - public KafkaDataExBuilder typeId( - int typeId) - { - dataExRW.typeId(typeId); - return this; - } + public KafkaConsumerBeginExBuilder consumerId( + String consumerId) + { + consumerBeginExRW.consumerId(consumerId); + return this; + } - public KafkaMergedDataExBuilder merged() - { - dataExRW.kind(KafkaApi.MERGED.value()); + public KafkaConsumerBeginExBuilder timeout( + int timeout) + { + consumerBeginExRW.timeout(timeout); + return this; + } - return new KafkaMergedDataExBuilder(); - } + public KafkaConsumerBeginExBuilder topic( + String topic) + { + consumerBeginExRW.topic(topic); + return this; + } - public KafkaFetchDataExBuilder fetch() - { - dataExRW.kind(KafkaApi.FETCH.value()); + public KafkaConsumerBeginExBuilder partition( + int partitionId) + { + partitionsRW.item(i -> i.partitionId(partitionId)); + return this; + } - return new KafkaFetchDataExBuilder(); + public KafkaBeginExBuilder build() + { + consumerBeginExRW.partitionIds(partitionsRW.build()); + final KafkaConsumerBeginExFW consumerBeginEx = consumerBeginExRW.build(); + beginExRO.wrap(writeBuffer, 0, consumerBeginEx.limit()); + return KafkaBeginExBuilder.this; + } } - public KafkaMetaDataExBuilder meta() + public final class KafkaOffsetFetchBeginExBuilder { - dataExRW.kind(KafkaApi.META.value()); - - return new KafkaMetaDataExBuilder(); - } + private final KafkaOffsetFetchBeginExFW.Builder offsetFetchBeginExRW = new KafkaOffsetFetchBeginExFW.Builder(); - public KafkaDescribeDataExBuilder describe() - { - dataExRW.kind(KafkaApi.DESCRIBE.value()); - return new KafkaDescribeDataExBuilder(); - } + private KafkaOffsetFetchBeginExBuilder() + { + offsetFetchBeginExRW.wrap(writeBuffer, KafkaBeginExFW.FIELD_OFFSET_OFFSET_FETCH, writeBuffer.capacity()); + } + + public KafkaOffsetFetchBeginExBuilder groupId( + String groupId) + { + offsetFetchBeginExRW.groupId(groupId); + return this; + } + + public KafkaOffsetFetchBeginExBuilder topic( + String topic, + int partitionId) + { + offsetFetchBeginExRW.topics(t -> t.item(i -> + i.topic(topic) + .partitions(p -> p.item(a -> a.partitionId(partitionId))))); + return this; + } + + public KafkaBeginExBuilder build() + { + final KafkaOffsetFetchBeginExFW consumerBeginEx = offsetFetchBeginExRW.build(); + beginExRO.wrap(writeBuffer, 0, consumerBeginEx.limit()); + return KafkaBeginExBuilder.this; + } + } + + public final class KafkaOffsetCommitBeginExBuilder + { + private final KafkaOffsetCommitBeginExFW.Builder offsetCommitBeginExRW = new KafkaOffsetCommitBeginExFW.Builder(); + + + private KafkaOffsetCommitBeginExBuilder() + { + offsetCommitBeginExRW.wrap(writeBuffer, KafkaBeginExFW.FIELD_OFFSET_OFFSET_COMMIT, writeBuffer.capacity()); + } + + public KafkaOffsetCommitBeginExBuilder groupId( + String groupId) + { + offsetCommitBeginExRW.groupId(groupId); + return this; + } + + public KafkaOffsetCommitBeginExBuilder topic( + String topic) + { + offsetCommitBeginExRW.topic(topic); + return this; + } + + public KafkaBeginExBuilder build() + { + final KafkaOffsetCommitBeginExFW offsetCommitBeginEx = offsetCommitBeginExRW.build(); + beginExRO.wrap(writeBuffer, 0, offsetCommitBeginEx.limit()); + return KafkaBeginExBuilder.this; + } + } + } + + public static final class KafkaDataExBuilder + { + private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + + private final KafkaDataExFW dataExRO = new KafkaDataExFW(); + + private final KafkaDataExFW.Builder dataExRW = new KafkaDataExFW.Builder(); + + private KafkaDataExBuilder() + { + dataExRW.wrap(writeBuffer, 0, writeBuffer.capacity()); + } + + public KafkaDataExBuilder typeId( + int typeId) + { + dataExRW.typeId(typeId); + return this; + } + + public KafkaMergedDataExBuilder merged() + { + dataExRW.kind(KafkaApi.MERGED.value()); + + return new KafkaMergedDataExBuilder(); + } + + public KafkaFetchDataExBuilder fetch() + { + dataExRW.kind(KafkaApi.FETCH.value()); + + return new KafkaFetchDataExBuilder(); + } + + public KafkaMetaDataExBuilder meta() + { + dataExRW.kind(KafkaApi.META.value()); + + return new KafkaMetaDataExBuilder(); + } + + public KafkaDescribeDataExBuilder describe() + { + dataExRW.kind(KafkaApi.DESCRIBE.value()); + + return new KafkaDescribeDataExBuilder(); + } public KafkaProduceDataExBuilder produce() { @@ -1070,11 +1578,25 @@ public KafkaProduceDataExBuilder produce() return new KafkaProduceDataExBuilder(); } - public KafkaGroupDataExBuilder group() + public KafkaConsumerDataExBuilder consumer() { - dataExRW.kind(KafkaApi.GROUP.value()); + dataExRW.kind(KafkaApi.CONSUMER.value()); - return new KafkaGroupDataExBuilder(); + return new KafkaConsumerDataExBuilder(); + } + + public KafkaOffsetFetchDataExBuilder offsetFetch() + { + dataExRW.kind(KafkaApi.OFFSET_FETCH.value()); + + return new KafkaOffsetFetchDataExBuilder(); + } + + public KafkaOffsetCommitDataExBuilder offsetCommit() + { + dataExRW.kind(KafkaApi.OFFSET_COMMIT.value()); + + return new KafkaOffsetCommitDataExBuilder(); } public byte[] build() @@ -1218,6 +1740,7 @@ public KafkaDataExBuilder build() public final class KafkaMergedDataExBuilder { private final DirectBuffer keyRO = new UnsafeBuffer(0, 0); + private final DirectBuffer hashKeyRO = new UnsafeBuffer(0, 0); private final DirectBuffer nameRO = new UnsafeBuffer(0, 0); private final DirectBuffer valueRO = new UnsafeBuffer(0, 0); @@ -1306,6 +1829,23 @@ public KafkaMergedDataExBuilder key( return this; } + public KafkaMergedDataExBuilder hashKey( + String hashKey) + { + if (hashKey == null) + { + mergedDataExRW.hashKey(m -> m.length(-1) + .value((OctetsFW) null)); + } + else + { + hashKeyRO.wrap(hashKey.getBytes(UTF_8)); + mergedDataExRW.hashKey(k -> k.length(hashKeyRO.capacity()) + .value(hashKeyRO, 0, hashKeyRO.capacity())); + } + return this; + } + public KafkaMergedDataExBuilder delta( String deltaType, long ancestorOffset) @@ -1574,33 +2114,126 @@ public KafkaDataExBuilder build() } } - public final class KafkaGroupDataExBuilder + public final class KafkaConsumerDataExBuilder { - private final KafkaGroupDataExFW.Builder groupDataExRW = new KafkaGroupDataExFW.Builder(); + private final KafkaConsumerDataExFW.Builder consumerDataExRW = new KafkaConsumerDataExFW.Builder(); - private KafkaGroupDataExBuilder() + private KafkaConsumerDataExBuilder() { - groupDataExRW.wrap(writeBuffer, KafkaDataExFW.FIELD_OFFSET_GROUP, writeBuffer.capacity()); + consumerDataExRW.wrap(writeBuffer, KafkaDataExFW.FIELD_OFFSET_CONSUMER, writeBuffer.capacity()); } - public KafkaGroupDataExBuilder leaderId( - String leaderId) + public KafkaConsumerDataExBuilder partition( + int partitionId) { - groupDataExRW.leaderId(leaderId); + consumerDataExRW.partitionsItem(p -> p.partitionId(partitionId)); return this; } - public KafkaGroupDataExBuilder memberId( - String memberId) + public KafkaConsumerBuilder consumer() + { + KafkaConsumerBuilder kafkaConsumerBuilder = new KafkaConsumerBuilder(); + return kafkaConsumerBuilder; + } + + public KafkaDataExBuilder build() { - groupDataExRW.memberId(memberId); + final KafkaConsumerDataExFW consumerDataEx = consumerDataExRW.build(); + dataExRO.wrap(writeBuffer, 0, consumerDataEx.limit()); + return KafkaDataExBuilder.this; + } + + class KafkaConsumerBuilder + { + private final MutableDirectBuffer consumerBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final KafkaConsumerAssignmentFW.Builder consumerRW = new KafkaConsumerAssignmentFW.Builder(); + + KafkaConsumerBuilder() + { + consumerRW.wrap(consumerBuffer, 0, consumerBuffer.capacity()); + } + + public KafkaConsumerBuilder id( + String id) + { + consumerRW.consumerId(id); + return this; + } + + public KafkaConsumerBuilder partition( + int partitionId) + { + consumerRW.partitionsItem(p -> p.partitionId(partitionId)); + return this; + } + + public KafkaConsumerDataExBuilder build() + { + KafkaConsumerAssignmentFW consumer = consumerRW.build(); + consumerDataExRW.assignmentsItem(a -> a + .consumerId(consumer.consumerId()) + .partitions(consumer.partitions())); + + return KafkaConsumerDataExBuilder.this; + } + } + } + + public final class KafkaOffsetFetchDataExBuilder + { + private final KafkaOffsetFetchDataExFW.Builder offsetFetchDataExRW = new KafkaOffsetFetchDataExFW.Builder(); + + private KafkaOffsetFetchDataExBuilder() + { + offsetFetchDataExRW.wrap(writeBuffer, KafkaDataExFW.FIELD_OFFSET_OFFSET_FETCH, writeBuffer.capacity()); + } + + public KafkaOffsetFetchDataExBuilder topic( + String topic, + int partitionId, + long offset) + { + offsetFetchDataExRW.topic(t -> + t.topic(topic).offsets(o -> o.item(i -> + i.partitionId(partitionId).partitionOffset(offset)))); return this; } public KafkaDataExBuilder build() { - final KafkaGroupDataExFW groupDataEx = groupDataExRW.build(); - dataExRO.wrap(writeBuffer, 0, groupDataEx.limit()); + final KafkaOffsetFetchDataExFW offsetFetchDataEx = offsetFetchDataExRW.build(); + dataExRO.wrap(writeBuffer, 0, offsetFetchDataEx.limit()); + return KafkaDataExBuilder.this; + } + } + + public final class KafkaOffsetCommitDataExBuilder + { + private final KafkaOffsetCommitDataExFW.Builder offsetCommitDataExRW = new KafkaOffsetCommitDataExFW.Builder(); + + private KafkaOffsetCommitDataExBuilder() + { + offsetCommitDataExRW.wrap(writeBuffer, KafkaDataExFW.FIELD_OFFSET_OFFSET_COMMIT, writeBuffer.capacity()); + } + + public KafkaOffsetCommitDataExBuilder partitionId( + int partitionId) + { + offsetCommitDataExRW.partitionId(partitionId); + return this; + } + + public KafkaOffsetCommitDataExBuilder partitionOffset( + long partitionId) + { + offsetCommitDataExRW.partitionOffset(partitionId); + return this; + } + + public KafkaDataExBuilder build() + { + final KafkaOffsetCommitDataExFW consumerDataEx = offsetCommitDataExRW.build(); + dataExRO.wrap(writeBuffer, 0, consumerDataEx.limit()); return KafkaDataExBuilder.this; } } @@ -1648,6 +2281,13 @@ public KafkaProduceFlushExBuilder produce() return new KafkaProduceFlushExBuilder(); } + public KafkaGroupFlushExBuilder group() + { + flushExRW.kind(KafkaApi.GROUP.value()); + + return new KafkaGroupFlushExBuilder(); + } + public byte[] build() { final KafkaFlushExFW flushEx = flushExRO; @@ -1662,105 +2302,182 @@ public final class KafkaMergedFlushExBuilder private KafkaMergedFlushExBuilder() { - mergedFlushExRW.wrap(writeBuffer, KafkaFlushExFW.FIELD_OFFSET_FETCH, writeBuffer.capacity()); + mergedFlushExRW.wrap(writeBuffer, KafkaFlushExFW.FIELD_OFFSET_MERGED, writeBuffer.capacity()); } - public KafkaMergedFlushExBuilder progress( - int partitionId, - long offset) + public KafkaMergedFetchFlushExBuilder fetch() { - progress(partitionId, offset, DEFAULT_LATEST_OFFSET); - return this; + mergedFlushExRW.kind(KafkaApi.FETCH.value()); + + return new KafkaMergedFetchFlushExBuilder(); } - public KafkaMergedFlushExBuilder progress( - int partitionId, - long offset, - long latestOffset) + public KafkaMergedConsumerFlushExBuilder consumer() { - mergedFlushExRW.progressItem(p -> p.partitionId(partitionId).partitionOffset(offset).latestOffset(latestOffset)); - return this; + mergedFlushExRW.kind(KafkaApi.CONSUMER.value()); + + return new KafkaMergedConsumerFlushExBuilder(); } - public KafkaMergedFlushExBuilder progress( + public KafkaFlushExBuilder build() + { + final KafkaMergedFlushExFW mergedFlushEx = mergedFlushExRW.build(); + flushExRO.wrap(writeBuffer, 0, mergedFlushEx.limit()); + return KafkaFlushExBuilder.this; + } + + public final class KafkaMergedFetchFlushExBuilder + { + private final KafkaMergedFetchFlushExFW.Builder mergedFetchFlushExRW = new KafkaMergedFetchFlushExFW.Builder(); + + private KafkaMergedFetchFlushExBuilder() + { + mergedFetchFlushExRW.wrap(writeBuffer, + KafkaFlushExFW.FIELD_OFFSET_MERGED + KafkaMergedFlushExFW.FIELD_OFFSET_FETCH, + writeBuffer.capacity()); + } + + public KafkaMergedFetchFlushExBuilder progress( + int partitionId, + long offset) + { + progress(partitionId, offset, DEFAULT_LATEST_OFFSET); + return this; + } + + public KafkaMergedFetchFlushExBuilder progress( + int partitionId, + long offset, + long latestOffset) + { + mergedFetchFlushExRW.progressItem(p -> + p.partitionId(partitionId) + .partitionOffset(offset) + .latestOffset(latestOffset)); + return this; + } + + public KafkaMergedFetchFlushExBuilder progress( int partitionId, long offset, long stableOffset, long latestOffset) - { - mergedFlushExRW.progressItem(p -> p + { + mergedFetchFlushExRW.progressItem(p -> p .partitionId(partitionId) .partitionOffset(offset) .stableOffset(stableOffset) .latestOffset(latestOffset)); - return this; - } + return this; + } - public KafkaMergedFlushExBuilder capabilities( - String capabilities) - { - mergedFlushExRW.capabilities(c -> c.set(KafkaCapabilities.valueOf(capabilities))); - return this; - } + public KafkaMergedFetchFlushExBuilder capabilities( + String capabilities) + { + mergedFetchFlushExRW.capabilities(c -> c.set(KafkaCapabilities.valueOf(capabilities))); + return this; + } - public KafkaFilterBuilder filter() - { - return new KafkaFilterBuilder<>() + public KafkaFilterBuilder filter() { + return new KafkaFilterBuilder<>() + { - @Override - protected KafkaMergedFlushExBuilder build( - KafkaFilterFW filter) + @Override + protected KafkaMergedFetchFlushExBuilder build( + KafkaFilterFW filter) + { + mergedFetchFlushExRW.filtersItem(fb -> set(fb, filter)); + return KafkaFlushExBuilder.KafkaMergedFlushExBuilder.KafkaMergedFetchFlushExBuilder.this; + } + }; + } + + public KafkaMergedFetchFlushExBuilder partition( + int partitionId, + long partitionOffset) + { + partition(partitionId, partitionOffset, DEFAULT_LATEST_OFFSET); + return this; + } + + public KafkaMergedFetchFlushExBuilder partition( + int partitionId, + long partitionOffset, + long latestOffset) + { + mergedFetchFlushExRW.partition(p -> p + .partitionId(partitionId) + .partitionOffset(partitionOffset) + .latestOffset(latestOffset)); + return this; + } + + + public KafkaMergedFetchFlushExBuilder key( + String key) + { + if (key == null) { - mergedFlushExRW.filtersItem(fb -> set(fb, filter)); - return KafkaMergedFlushExBuilder.this; + mergedFetchFlushExRW.key(m -> m.length(-1) + .value((OctetsFW) null)); } - }; - } + else + { + keyRO.wrap(key.getBytes(UTF_8)); + mergedFetchFlushExRW.key(k -> k.length(keyRO.capacity()) + .value(keyRO, 0, keyRO.capacity())); + } + return this; + } - public KafkaMergedFlushExBuilder partition( - int partitionId, - long partitionOffset) - { - partition(partitionId, partitionOffset, DEFAULT_LATEST_OFFSET); - return this; + public KafkaFlushExBuilder build() + { + final KafkaMergedFetchFlushExFW mergedFetchFlushEx = mergedFetchFlushExRW.build(); + flushExRO.wrap(writeBuffer, 0, mergedFetchFlushExRW.limit()); + return KafkaFlushExBuilder.this; + } } - public KafkaMergedFlushExBuilder partition( - int partitionId, - long partitionOffset, - long latestOffset) + public final class KafkaMergedConsumerFlushExBuilder { - mergedFlushExRW.partition(p -> p - .partitionId(partitionId) - .partitionOffset(partitionOffset) - .latestOffset(latestOffset)); - return this; - } + private final KafkaMergedConsumerFlushExFW.Builder mergedConsumerFlushExRW = + new KafkaMergedConsumerFlushExFW.Builder(); + private KafkaMergedConsumerFlushExBuilder() + { + mergedConsumerFlushExRW.wrap(writeBuffer, + KafkaFlushExFW.FIELD_OFFSET_MERGED + KafkaMergedFlushExFW.FIELD_OFFSET_CONSUMER, + writeBuffer.capacity()); + } - public KafkaMergedFlushExBuilder key( - String key) - { - if (key == null) + public KafkaMergedConsumerFlushExBuilder partition( + int partitionId, + long partitionOffset) { - mergedFlushExRW.key(m -> m.length(-1) - .value((OctetsFW) null)); + partition(partitionId, partitionOffset, DEFAULT_LATEST_OFFSET); + return this; } - else + + public KafkaMergedConsumerFlushExBuilder partition( + int partitionId, + long partitionOffset, + long latestOffset) { - keyRO.wrap(key.getBytes(UTF_8)); - mergedFlushExRW.key(k -> k.length(keyRO.capacity()) - .value(keyRO, 0, keyRO.capacity())); + mergedConsumerFlushExRW.partition(p -> p + .partitionId(partitionId) + .partitionOffset(partitionOffset) + .latestOffset(latestOffset)); + return this; } - return this; - } - public KafkaFlushExBuilder build() - { - final KafkaMergedFlushExFW mergedFlushEx = mergedFlushExRW.build(); - flushExRO.wrap(writeBuffer, 0, mergedFlushEx.limit()); - return KafkaFlushExBuilder.this; + public KafkaFlushExBuilder build() + { + final KafkaMergedConsumerFlushExFW mergedConsumerFlushEx = mergedConsumerFlushExRW.build(); + flushExRO.wrap(writeBuffer, 0, mergedConsumerFlushExRW.limit()); + return KafkaFlushExBuilder.this; + } } } @@ -1797,9 +2514,9 @@ public KafkaFetchFlushExBuilder partition( long latestOffset) { fetchFlushExRW.partition(p -> p.partitionId(partitionId) - .partitionOffset(offset) - .stableOffset(stableOffset) - .latestOffset(latestOffset)); + .partitionOffset(offset) + .stableOffset(stableOffset) + .latestOffset(latestOffset)); return this; } @@ -1889,6 +2606,59 @@ public KafkaFlushExBuilder build() return KafkaFlushExBuilder.this; } } + + public final class KafkaGroupFlushExBuilder + { + private final MutableDirectBuffer memberBuffer = new UnsafeBuffer(new byte[1024 * 8]); + private final KafkaGroupFlushExFW.Builder flushGroupExRW = new KafkaGroupFlushExFW.Builder(); + private final Array32FW.Builder memberRW = + new Array32FW.Builder<>(new KafkaGroupMemberFW.Builder(), new KafkaGroupMemberFW()); + + private KafkaGroupFlushExBuilder() + { + flushGroupExRW.wrap(writeBuffer, KafkaFlushExFW.FIELD_OFFSET_GROUP, writeBuffer.capacity()); + memberRW.wrap(memberBuffer, 0, memberBuffer.capacity()); + } + + public KafkaGroupFlushExBuilder leaderId( + String leaderId) + { + flushGroupExRW.leaderId(leaderId); + return this; + } + + public KafkaGroupFlushExBuilder memberId( + String memberId) + { + flushGroupExRW.memberId(memberId); + return this; + } + + public KafkaGroupFlushExBuilder members( + String memberId, + byte[] metadata) + { + memberRW.item(gm -> gm.id(memberId) + .metadataLen(metadata.length) + .metadata(md -> md.set(metadata))); + return this; + } + + public KafkaGroupFlushExBuilder members( + String memberId) + { + memberRW.item(gm -> gm.id(memberId)); + return this; + } + + public KafkaFlushExBuilder build() + { + flushGroupExRW.members(memberRW.build()); + final KafkaGroupFlushExFW groupFlushEx = flushGroupExRW.build(); + flushExRO.wrap(writeBuffer, 0, groupFlushEx.limit()); + return KafkaFlushExBuilder.this; + } + } } public static final class KafkaResetExBuilder @@ -1918,6 +2688,13 @@ public KafkaResetExBuilder error( return this; } + public KafkaResetExBuilder consumerId( + String consumerId) + { + resetExRW.consumerId(consumerId); + return this; + } + public byte[] build() { final KafkaResetExFW resetEx = resetExRW.build(); @@ -1932,6 +2709,7 @@ public static final class KafkaDataExMatcherBuilder private final DirectBuffer bufferRO = new UnsafeBuffer(); private final DirectBuffer keyRO = new UnsafeBuffer(0, 0); + private final DirectBuffer hashKeyRO = new UnsafeBuffer(0, 0); private final DirectBuffer nameRO = new UnsafeBuffer(0, 0); private final DirectBuffer valueRO = new UnsafeBuffer(0, 0); @@ -1968,15 +2746,6 @@ public KafkaProduceDataExMatcherBuilder produce() return matcherBuilder; } - public KafkaGroupDataExMatchBuilder group() - { - final KafkaGroupDataExMatchBuilder matcherBuilder = new KafkaGroupDataExMatchBuilder(); - - this.kind = KafkaApi.GROUP.value(); - this.caseMatcher = matcherBuilder::match; - return matcherBuilder; - } - public KafkaDataExMatcherBuilder typeId( int typeId) { @@ -2397,6 +3166,7 @@ public final class KafkaMergedDataExMatcherBuilder private Array32FW.Builder progressRW; private KafkaDeltaFW.Builder deltaRW; private KafkaKeyFW.Builder keyRW; + private KafkaKeyFW.Builder hashKeyRW; private Array32FW.Builder headersRW; private KafkaMergedDataExMatcherBuilder() @@ -2488,6 +3258,27 @@ public KafkaMergedDataExMatcherBuilder key( return this; } + public KafkaMergedDataExMatcherBuilder hashKey( + String hashKey) + { + assert hashKeyRW == null; + hashKeyRW = new KafkaKeyFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + + if (hashKey == null) + { + hashKeyRW.length(-1) + .value((OctetsFW) null); + } + else + { + hashKeyRO.wrap(hashKey.getBytes(UTF_8)); + hashKeyRW.length(hashKeyRO.capacity()) + .value(hashKeyRO, 0, hashKeyRO.capacity()); + } + + return this; + } + public KafkaMergedDataExMatcherBuilder delta( String delta, long ancestorOffset) @@ -2664,6 +3455,7 @@ private boolean match( matchDeferred(mergedDataEx) && matchTimestamp(mergedDataEx) && matchKey(mergedDataEx) && + matchHashKey(mergedDataEx) && matchDelta(mergedDataEx) && matchHeaders(mergedDataEx) && matchFilters(mergedDataEx); @@ -2699,71 +3491,28 @@ private boolean matchKey( return keyRW == null || keyRW.build().equals(mergedDataEx.key()); } - private boolean matchDelta( + private boolean matchHashKey( final KafkaMergedDataExFW mergedDataEx) { - return deltaRW == null || deltaRW.build().equals(mergedDataEx.delta()); - } - - private boolean matchHeaders( - final KafkaMergedDataExFW mergedDataEx) - { - return headersRW == null || headersRW.build().equals(mergedDataEx.headers()); - } - - private boolean matchFilters( - final KafkaMergedDataExFW mergedDataEx) - { - return filters == null || filters == mergedDataEx.filters(); - } - } - - public final class KafkaGroupDataExMatchBuilder - { - private String16FW leaderId; - private String16FW memberId; - - private KafkaGroupDataExMatchBuilder() - { - } - - public KafkaGroupDataExMatchBuilder leaderId( - String leaderId) - { - this.leaderId = new String16FW(leaderId); - return this; - } - - public KafkaGroupDataExMatchBuilder memberId( - String memberId) - { - this.memberId = new String16FW(memberId); - return this; - } - - public KafkaDataExMatcherBuilder build() - { - return KafkaDataExMatcherBuilder.this; + return hashKeyRW == null || hashKeyRW.build().equals(mergedDataEx.hashKey()); } - private boolean match( - KafkaDataExFW dataEx) + private boolean matchDelta( + final KafkaMergedDataExFW mergedDataEx) { - final KafkaGroupDataExFW groupDataEx = dataEx.group(); - return matchLeaderId(groupDataEx) && - matchMemberId(groupDataEx); + return deltaRW == null || deltaRW.build().equals(mergedDataEx.delta()); } - private boolean matchLeaderId( - final KafkaGroupDataExFW groupDataEx) + private boolean matchHeaders( + final KafkaMergedDataExFW mergedDataEx) { - return leaderId == null || leaderId.equals(groupDataEx.leaderId()); + return headersRW == null || headersRW.build().equals(mergedDataEx.headers()); } - private boolean matchMemberId( - final KafkaGroupDataExFW groupDataEx) + private boolean matchFilters( + final KafkaMergedDataExFW mergedDataEx) { - return memberId == null || memberId.equals(groupDataEx.memberId()); + return filters == null || filters == mergedDataEx.filters(); } } } @@ -2806,6 +3555,15 @@ public KafkaProduceFlushExMatcherBuilder produce() return matcherBuilder; } + public KafkaGroupFlushExMatchBuilder group() + { + final KafkaGroupFlushExMatchBuilder matcherBuilder = new KafkaGroupFlushExMatchBuilder(); + + this.kind = KafkaApi.GROUP.value(); + this.caseMatcher = matcherBuilder::match; + return matcherBuilder; + } + public KafkaFlushExMatcherBuilder typeId( int typeId) { @@ -2929,7 +3687,6 @@ public KafkaFilterBuilder() { - @Override protected KafkaFlushExMatcherBuilder.KafkaFetchFlushExMatcherBuilder build( KafkaFilterFW filter) @@ -2971,162 +3728,207 @@ private boolean matchFilters( { return filtersRW == null || filtersRW.build().equals(fetchFlushEx.filters()); } - } public final class KafkaMergedFlushExMatcherBuilder { - private Array32FW.Builder progressRW; - private KafkaKeyFW.Builder keyRW; - private KafkaOffsetFW.Builder partitionRW; - - private Array32FW.Builder filtersRW; + KafkaMergedFetchFlushEx mergedFetchFlush; private KafkaMergedFlushExMatcherBuilder() { } - public KafkaMergedFlushExMatcherBuilder progress( - int partitionId, - long offset) - { - progress(partitionId, offset, DEFAULT_LATEST_OFFSET); - return this; - } - - public KafkaMergedFlushExMatcherBuilder progress( - int partitionId, - long offset, - long latestOffset) + public boolean match( + KafkaFlushExFW kafkaFlushEx) { - if (progressRW == null) + boolean matched = false; + if (kafkaFlushEx.merged().kind() == KafkaApi.FETCH.value()) { - this.progressRW = new Array32FW.Builder<>(new KafkaOffsetFW.Builder(), new KafkaOffsetFW()) - .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + matched = fetch().match(kafkaFlushEx); } - progressRW.item(i -> i.partitionId(partitionId).partitionOffset(offset).latestOffset(latestOffset)); - return this; + return matched; } - public KafkaMergedFlushExMatcherBuilder progress( - int partitionId, - long offset, - long stableOffset, - long latestOffset) + public KafkaMergedFetchFlushEx fetch() { - if (progressRW == null) + if (mergedFetchFlush == null) { - this.progressRW = new Array32FW.Builder<>(new KafkaOffsetFW.Builder(), new KafkaOffsetFW()) - .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + mergedFetchFlush = new KafkaMergedFetchFlushEx(); } - progressRW.item(i -> i - .partitionId(partitionId) - .partitionOffset(offset) - .stableOffset(stableOffset) - .latestOffset(latestOffset)); - return this; + return mergedFetchFlush; } - public KafkaMergedFlushExMatcherBuilder partition( - int partitionId, - long offset) + public final class KafkaMergedFetchFlushEx { - partition(partitionId, offset, DEFAULT_LATEST_OFFSET); - return this; - } + private Array32FW.Builder progressRW; + private KafkaKeyFW.Builder keyRW; + private KafkaOffsetFW.Builder partitionRW; + private KafkaCapabilities capabilities; - public KafkaMergedFlushExMatcherBuilder partition( - int partitionId, - long offset, - long latestOffset) - { - assert partitionRW == null; - partitionRW = new KafkaOffsetFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + private Array32FW.Builder filtersRW; - partitionRW.partitionId(partitionId).partitionOffset(offset).latestOffset(latestOffset); + private KafkaMergedFetchFlushEx() + { + } - return this; - } + public KafkaMergedFetchFlushEx capabilities( + String capabilities) + { + this.capabilities = KafkaCapabilities.valueOf(capabilities); + return this; + } - public KafkaMergedFlushExMatcherBuilder key( - String key) - { - assert keyRW == null; - keyRW = new KafkaKeyFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + public KafkaMergedFetchFlushEx progress( + int partitionId, + long offset) + { + progress(partitionId, offset, DEFAULT_LATEST_OFFSET); + return this; + } - if (key == null) + public KafkaMergedFetchFlushEx progress( + int partitionId, + long offset, + long latestOffset) { - keyRW.length(-1) - .value((OctetsFW) null); + if (progressRW == null) + { + this.progressRW = new Array32FW.Builder<>(new KafkaOffsetFW.Builder(), new KafkaOffsetFW()) + .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + } + progressRW.item(i -> i.partitionId(partitionId).partitionOffset(offset).latestOffset(latestOffset)); + return this; } - else + + public KafkaMergedFetchFlushEx progress( + int partitionId, + long offset, + long stableOffset, + long latestOffset) { - keyRO.wrap(key.getBytes(UTF_8)); - keyRW.length(keyRO.capacity()) - .value(keyRO, 0, keyRO.capacity()); + if (progressRW == null) + { + this.progressRW = new Array32FW.Builder<>(new KafkaOffsetFW.Builder(), new KafkaOffsetFW()) + .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + } + progressRW.item(i -> i + .partitionId(partitionId) + .partitionOffset(offset) + .stableOffset(stableOffset) + .latestOffset(latestOffset)); + return this; } - return this; - } + public KafkaMergedFetchFlushEx partition( + int partitionId, + long offset) + { + partition(partitionId, offset, DEFAULT_LATEST_OFFSET); + return this; + } - public KafkaFilterBuilder filter() - { - if (filtersRW == null) + public KafkaMergedFetchFlushEx partition( + int partitionId, + long offset, + long latestOffset) { - filtersRW = new Array32FW.Builder<>(new KafkaFilterFW.Builder(), new KafkaFilterFW()) - .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + assert partitionRW == null; + partitionRW = new KafkaOffsetFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + + partitionRW.partitionId(partitionId).partitionOffset(offset).latestOffset(latestOffset); + + return this; } - return new KafkaFilterBuilder<>() + public KafkaMergedFetchFlushEx key( + String key) { + assert keyRW == null; + keyRW = new KafkaKeyFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); - @Override - protected KafkaMergedFlushExMatcherBuilder build( - KafkaFilterFW filter) + if (key == null) { - filtersRW.item(fb -> set(fb, filter)); - return KafkaMergedFlushExMatcherBuilder.this; + keyRW.length(-1) + .value((OctetsFW) null); + } + else + { + keyRO.wrap(key.getBytes(UTF_8)); + keyRW.length(keyRO.capacity()) + .value(keyRO, 0, keyRO.capacity()); } - }; - } - public KafkaFlushExMatcherBuilder build() - { - return KafkaFlushExMatcherBuilder.this; - } + return this; + } - private boolean match( - KafkaFlushExFW flushEx) - { - final KafkaMergedFlushExFW mergedFlushEx = flushEx.merged(); - return matchProgress(mergedFlushEx) && - matchKey(mergedFlushEx) && - matchPartition(mergedFlushEx) && - matchFilters(mergedFlushEx); - } + public KafkaFilterBuilder + + filter() + { + if (filtersRW == null) + { + filtersRW = new Array32FW.Builder<>(new KafkaFilterFW.Builder(), new KafkaFilterFW()) + .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + } - private boolean matchProgress( - final KafkaMergedFlushExFW mergedFlushEx) - { - return progressRW == null || progressRW.build().equals(mergedFlushEx.progress()); - } + return new KafkaFilterBuilder<>() + { + @Override + protected KafkaFlushExMatcherBuilder.KafkaMergedFlushExMatcherBuilder.KafkaMergedFetchFlushEx + build( + KafkaFilterFW filter) + { + filtersRW.item(fb -> set(fb, filter)); + return KafkaMergedFetchFlushEx.this; + } + }; + } - private boolean matchPartition( - final KafkaMergedFlushExFW mergedFlushEx) - { - return partitionRW == null || partitionRW.build().equals(mergedFlushEx.partition()); - } + public KafkaFlushExMatcherBuilder build() + { + return KafkaFlushExMatcherBuilder.this; + } - private boolean matchKey( - final KafkaMergedFlushExFW mergedFlushEx) - { - return keyRW == null || keyRW.build().equals(mergedFlushEx.key()); - } + private boolean match( + KafkaFlushExFW flushEx) + { + final KafkaMergedFetchFlushExFW mergedFlushEx = flushEx.merged().fetch(); + return matchCapabilities(mergedFlushEx) && + matchProgress(mergedFlushEx) && + matchKey(mergedFlushEx) && + matchPartition(mergedFlushEx) && + matchFilters(mergedFlushEx); + } - private boolean matchFilters( - final KafkaMergedFlushExFW mergedFlushEx) - { - return filtersRW == null || filtersRW.build().equals(mergedFlushEx.filters()); + private boolean matchCapabilities( + final KafkaMergedFetchFlushExFW mergedFlushEx) + { + return capabilities == null || capabilities.equals(mergedFlushEx.capabilities().get()); + } + + private boolean matchProgress( + final KafkaMergedFetchFlushExFW mergedFlush) + { + return progressRW == null || progressRW.build().equals(mergedFlush.progress()); + } + + private boolean matchPartition( + final KafkaMergedFetchFlushExFW mergedFlush) + { + return partitionRW == null || partitionRW.build().equals(mergedFlush.partition()); + } + + private boolean matchKey( + final KafkaMergedFetchFlushExFW mergedFlush) + { + return keyRW == null || keyRW.build().equals(mergedFlush.key()); + } + + private boolean matchFilters( + final KafkaMergedFetchFlushExFW mergedFlush) + { + return filtersRW == null || filtersRW.build().equals(mergedFlush.filters()); + } } } @@ -3206,6 +4008,89 @@ private boolean matchKey( return keyRW == null || keyRW.build().equals(produceFlushEx.key()); } } + + public final class KafkaGroupFlushExMatchBuilder + { + private String16FW leaderId; + private String16FW memberId; + private Array32FW.Builder membersRW; + + private KafkaGroupFlushExMatchBuilder() + { + } + + public KafkaGroupFlushExMatchBuilder leaderId( + String leaderId) + { + this.leaderId = new String16FW(leaderId); + return this; + } + + public KafkaGroupFlushExMatchBuilder memberId( + String memberId) + { + this.memberId = new String16FW(memberId); + return this; + } + + public KafkaGroupFlushExMatchBuilder members( + String memberId, + String metadata) + { + if (membersRW == null) + { + this.membersRW = new Array32FW.Builder<>(new KafkaGroupMemberFW.Builder(), new KafkaGroupMemberFW()) + .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + } + this.membersRW.item(m -> m.id(memberId).metadataLen(metadata.length()) + .metadata(md -> md.set(metadata.getBytes()))); + return this; + } + + public KafkaGroupFlushExMatchBuilder members( + String memberId) + { + if (membersRW == null) + { + this.membersRW = new Array32FW.Builder<>(new KafkaGroupMemberFW.Builder(), new KafkaGroupMemberFW()) + .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); + } + this.membersRW.item(m -> m.id(memberId)); + return this; + } + + public KafkaFlushExMatcherBuilder build() + { + return KafkaFlushExMatcherBuilder.this; + } + + private boolean match( + KafkaFlushExFW flushEx) + { + final KafkaGroupFlushExFW groupFlushEx = flushEx.group(); + return matchLeaderId(groupFlushEx) && + matchMemberId(groupFlushEx) && + matchMembers(groupFlushEx); + } + + private boolean matchLeaderId( + final KafkaGroupFlushExFW groupFLushEx) + { + return leaderId == null || leaderId.equals(groupFLushEx.leaderId()); + } + + private boolean matchMemberId( + final KafkaGroupFlushExFW groupFLushEx) + { + return memberId == null || memberId.equals(groupFLushEx.memberId()); + } + + private boolean matchMembers( + final KafkaGroupFlushExFW groupFLushEx) + { + return membersRW == null || membersRW.build().equals(groupFLushEx.members()); + } + } } public static final class KafkaBeginExMatcherBuilder @@ -3579,6 +4464,8 @@ public final class KafkaGroupBeginExMatcherBuilder private String16FW protocol; private int timeout; + private byte[] metadata; + private KafkaGroupBeginExMatcherBuilder() { } @@ -3604,6 +4491,13 @@ public KafkaGroupBeginExMatcherBuilder timeout( return this; } + public KafkaGroupBeginExMatcherBuilder metadata( + byte[] metadata) + { + this.metadata = metadata; + return this; + } + public KafkaBeginExMatcherBuilder build() { return KafkaBeginExMatcherBuilder.this; @@ -3616,7 +4510,8 @@ private boolean match( return matchGroupId(groupBeginEx) && matchGroupId(groupBeginEx) && matchProtocol(groupBeginEx) && - matchTimeout(groupBeginEx); + matchTimeout(groupBeginEx) && + matchMetadata(groupBeginEx); } private boolean matchGroupId( @@ -3636,12 +4531,21 @@ private boolean matchTimeout( { return timeout == 0 || timeout == groupBeginExFW.timeout(); } + + private boolean matchMetadata( + final KafkaGroupBeginExFW groupBeginExFW) + { + OctetsFW metadata = groupBeginExFW.metadata(); + return this.metadata == null || metadata.sizeof() == this.metadata.length; + } } public final class KafkaMergedBeginExMatcherBuilder { private KafkaCapabilities capabilities; private String16FW topic; + private String16FW groupId; + private String16FW consumerId; private Array32FW.Builder partitionsRW; private KafkaIsolation isolation; private KafkaDeltaType deltaType; @@ -3668,6 +4572,20 @@ public KafkaMergedBeginExMatcherBuilder topic( return this; } + public KafkaMergedBeginExMatcherBuilder groupId( + String groupId) + { + this.groupId = new String16FW(groupId); + return this; + } + + public KafkaMergedBeginExMatcherBuilder consumerId( + String consumerId) + { + this.consumerId = new String16FW(consumerId); + return this; + } + public KafkaMergedBeginExMatcherBuilder partition( int partitionId, long offset) @@ -3768,6 +4686,8 @@ private boolean match( final KafkaMergedBeginExFW mergedBeginEx = beginEx.merged(); return matchCapabilities(mergedBeginEx) && matchTopic(mergedBeginEx) && + matchGroupId(mergedBeginEx) && + matchConsumerId(mergedBeginEx) && matchPartitions(mergedBeginEx) && matchFilters(mergedBeginEx) && matchIsolation(mergedBeginEx) && @@ -3788,6 +4708,18 @@ private boolean matchTopic( return topic == null || topic.equals(mergedBeginEx.topic()); } + private boolean matchGroupId( + final KafkaMergedBeginExFW mergedBeginEx) + { + return groupId == null || groupId.equals(mergedBeginEx.groupId()); + } + + private boolean matchConsumerId( + final KafkaMergedBeginExFW mergedBeginEx) + { + return consumerId == null || consumerId.equals(mergedBeginEx.consumerId()); + } + private boolean matchPartitions( final KafkaMergedBeginExFW mergedBeginEx) { diff --git a/specs/binding-kafka.spec/src/main/resources/META-INF/zilla/kafka.idl b/specs/binding-kafka.spec/src/main/resources/META-INF/zilla/kafka.idl index ea3adcc86c..fb0078d524 100644 --- a/specs/binding-kafka.spec/src/main/resources/META-INF/zilla/kafka.idl +++ b/specs/binding-kafka.spec/src/main/resources/META-INF/zilla/kafka.idl @@ -166,38 +166,47 @@ scope kafka { enum KafkaApi (uint8) { + CONSUMER (252), + GROUP (253), BOOTSTRAP (254), MERGED (255), META (3), + OFFSET_COMMIT (8), + OFFSET_FETCH (9), DESCRIBE (32), FETCH (1), - PRODUCE (0), - GROUP (10) + PRODUCE (0) } union KafkaBeginEx switch (uint8) extends core::stream::Extension { + case 252: kafka::stream::KafkaConsumerBeginEx consumer; + case 253: kafka::stream::KafkaGroupBeginEx group; case 254: kafka::stream::KafkaBootstrapBeginEx bootstrap; case 255: kafka::stream::KafkaMergedBeginEx merged; case 3: kafka::stream::KafkaMetaBeginEx meta; + case 8: kafka::stream::KafkaOffsetCommitBeginEx offsetCommit; + case 9: kafka::stream::KafkaOffsetFetchBeginEx offsetFetch; case 32: kafka::stream::KafkaDescribeBeginEx describe; case 1: kafka::stream::KafkaFetchBeginEx fetch; case 0: kafka::stream::KafkaProduceBeginEx produce; - case 10: kafka::stream::KafkaGroupBeginEx group; } union KafkaDataEx switch (uint8) extends core::stream::Extension { + case 252: kafka::stream::KafkaConsumerDataEx consumer; case 255: kafka::stream::KafkaMergedDataEx merged; case 3: kafka::stream::KafkaMetaDataEx meta; + case 8: kafka::stream::KafkaOffsetCommitDataEx offsetCommit; + case 9: kafka::stream::KafkaOffsetFetchDataEx offsetFetch; case 32: kafka::stream::KafkaDescribeDataEx describe; case 1: kafka::stream::KafkaFetchDataEx fetch; case 0: kafka::stream::KafkaProduceDataEx produce; - case 10: kafka::stream::KafkaGroupDataEx group; } union KafkaFlushEx switch (uint8) extends core::stream::Extension { + case 253: kafka::stream::KafkaGroupFlushEx group; case 255: kafka::stream::KafkaMergedFlushEx merged; case 1: kafka::stream::KafkaFetchFlushEx fetch; case 0: kafka::stream::KafkaProduceFlushEx produce; @@ -206,6 +215,7 @@ scope kafka struct KafkaResetEx extends core::stream::Extension { int32 error = 0; + string16 consumerId = null; } struct KafkaBootstrapBeginEx @@ -217,6 +227,9 @@ scope kafka { KafkaCapabilities capabilities = PRODUCE_AND_FETCH; string16 topic; + string16 groupId = null; + string16 consumerId = null; + int32 timeout = 0; KafkaOffset[] partitions; KafkaFilter[] filters; // ORed KafkaEvaluation evaluation = LAZY; @@ -229,15 +242,22 @@ scope kafka { int32 deferred = 0; // INIT only (TODO: move to DATA frame) int64 timestamp = 0; // INIT only - int64 filters = -1; // INIT only + int64 filters = -1; // INIT only KafkaOffset partition; // INIT only KafkaOffset[] progress; // INIT only KafkaKey key; // INIT only + KafkaKey hashKey; // INIT only KafkaDelta delta; // INIT + FIN KafkaHeader[] headers; // INIT + FIN (produce), INIT only (fetch) } - struct KafkaMergedFlushEx + union KafkaMergedFlushEx switch (uint8) + { + case 252: kafka::stream::KafkaMergedConsumerFlushEx consumer; + case 1: kafka::stream::KafkaMergedFetchFlushEx fetch; + } + + struct KafkaMergedFetchFlushEx { KafkaOffset partition; KafkaOffset[] progress; @@ -246,6 +266,11 @@ scope kafka KafkaKey key; } + struct KafkaMergedConsumerFlushEx + { + KafkaOffset partition; + } + struct KafkaMetaBeginEx { string16 topic; @@ -324,17 +349,132 @@ scope kafka KafkaHeader[] headers; } + struct KafkaTopicPartition + { + int32 partitionId; + } + + struct KafkaGroupTopicMetadata + { + string16 topic; + KafkaTopicPartition[] partitions; + } + + struct KafkaGroupMemberMetadata + { + string16 consumerId; + KafkaGroupTopicMetadata[] topics; + } + struct KafkaGroupBeginEx { string16 groupId; string16 protocol; int32 timeout; + varint32 metadataLen; + octets[metadataLen] metadata = null; + } + + struct KafkaGroupMember + { + string16 id; + varint32 metadataLen; + octets[metadataLen] metadata = null; } - struct KafkaGroupDataEx + struct KafkaGroupFlushEx { string16 leaderId; string16 memberId; + KafkaGroupMember[] members; + } + + struct KafkaConsumerBeginEx + { + string16 groupId; + string16 consumerId; + int32 timeout; + string16 topic; + KafkaTopicPartition[] partitionIds; + } + + struct KafkaConsumerAssignment + { + string16 consumerId; + KafkaTopicPartition[] partitions; + } + + struct KafkaConsumerDataEx + { + KafkaTopicPartition[] partitions; + KafkaConsumerAssignment[] assignments; + } + + struct KafkaOffsetFetchTopic + { + string16 topic; + KafkaTopicPartition[] partitions; + } + + struct KafkaOffsetFetchBeginEx + { + string16 groupId; + KafkaOffsetFetchTopic[] topics; + } + + struct KafkaOffsetFetchTopicOffsets + { + string16 topic; + KafkaOffset[] offsets; + } + + struct KafkaOffsetFetchDataEx + { + KafkaOffsetFetchTopicOffsets topic; + } + + struct KafkaOffsetCommitBeginEx + { + string16 groupId; + string16 topic; + } + + struct KafkaOffsetCommitDataEx + { + int32 partitionId; + int64 partitionOffset; + } + } + + scope rebalance + { + struct TopicPartition + { + int32 partitionId; + } + + struct ConsumerAssignment + { + string16 consumerId; + TopicPartition[] partitions; + } + + struct TopicAssignment + { + string16 topic; + TopicPartition[] partitions; + ConsumerAssignment[] userdata; + } + + struct MemberAssignment + { + string16 memberId; + TopicAssignment[] assignments; + } + + struct PartitionIndex + { + int32 index; } } } diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/schema/kafka.schema.patch.json b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/schema/kafka.schema.patch.json index 2b20c34eef..a27ea5f0a3 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/schema/kafka.schema.patch.json +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/schema/kafka.schema.patch.json @@ -11,7 +11,7 @@ { "if": { - "properties": + "properties": { "type": { @@ -218,6 +218,11 @@ { "title": "Topic", "type": "string" + }, + "groupId": + { + "title": "groupId", + "type": "string" } }, "additionalProperties": false diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/partition.assignment/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/partition.assignment/client.rpt new file mode 100644 index 0000000000..ff7a697a41 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/partition.assignment/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .consumer() + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .topic("test") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .consumer() + .partition(0) + .consumer() + .id("consumer-1") + .partition(0) + .build() + .consumer() + .id("consumer-2") + .partition(1) + .build() + .build() + .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/partition.assignment/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/partition.assignment/server.rpt new file mode 100644 index 0000000000..686b073ba8 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/partition.assignment/server.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .consumer() + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .topic("test") + .partition(0) + .partition(1) + .build() + .build()} + +connected + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .consumer() + .partition(0) + .consumer() + .id("consumer-1") + .partition(0) + .build() + .consumer() + .id("consumer-2") + .partition(1) + .build() + .build() + .build()} + +write zilla:data.empty +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/reassign.new.topic/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/reassign.new.topic/client.rpt new file mode 100644 index 0000000000..ceda6ed347 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/reassign.new.topic/client.rpt @@ -0,0 +1,83 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .consumer() + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .topic("test-1") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .consumer() + .partition(0) + .partition(1) + .consumer() + .id("consumer-1") + .partition(0) + .partition(1) + .build() + .build() + .build()} + +read notify RECEIVED_ASSIGNMENT + +connect await RECEIVED_ASSIGNMENT + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .consumer() + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .topic("test-2") + .partition(0) + .partition(1) + .partition(2) + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .consumer() + .partition(0) + .partition(1) + .partition(2) + .consumer() + .id("consumer-1") + .partition(0) + .partition(1) + .partition(2) + .build() + .build() + .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/reassign.new.topic/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/reassign.new.topic/server.rpt new file mode 100644 index 0000000000..43e2750393 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/consumer/reassign.new.topic/server.rpt @@ -0,0 +1,89 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .consumer() + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .topic("test-1") + .partition(0) + .partition(1) + .build() + .build()} + +connected + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .consumer() + .partition(0) + .partition(1) + .consumer() + .id("consumer-1") + .partition(0) + .partition(1) + .build() + .build() + .build()} +write zilla:data.empty +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .consumer() + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .topic("test-2") + .partition(0) + .partition(1) + .partition(2) + .build() + .build()} + +connected + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .consumer() + .partition(0) + .partition(1) + .partition(2) + .consumer() + .id("consumer-1") + .partition(0) + .partition(1) + .partition(2) + .build() + .build() + .build()} + +write zilla:data.empty +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/client.sent.write.abort.before.coordinator.response/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/client.sent.write.abort.before.coordinator.response/client.rpt new file mode 100644 index 0000000000..ca416d10ee --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/client.sent.write.abort.before.coordinator.response/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/client.sent.write.abort.before.coordinator.response/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/client.sent.write.abort.before.coordinator.response/server.rpt new file mode 100644 index 0000000000..6d3853b32e --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/client.sent.write.abort.before.coordinator.response/server.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/ignore.heartbeat.before.handshake/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/ignore.heartbeat.before.handshake/client.rpt new file mode 100644 index 0000000000..2576124653 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/ignore.heartbeat.before.handshake/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + option zilla:budgetId 1 + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +write advise zilla:flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/ignore.heartbeat.before.handshake/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/ignore.heartbeat.before.handshake/server.rpt new file mode 100644 index 0000000000..7076315b97 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/ignore.heartbeat.before.handshake/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +read advised zilla:flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/leader/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/leader/client.rpt new file mode 100644 index 0000000000..ee170242ea --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/leader/client.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/leader/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/leader/server.rpt new file mode 100644 index 0000000000..73e30d082e --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/leader/server.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/partition.assignment/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/partition.assignment/client.rpt new file mode 100644 index 0000000000..916fd3fc53 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/partition.assignment/client.rpt @@ -0,0 +1,115 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .members("memberId-2", kafka:memberMetadata() + .consumerId("consumer-2") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +write ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(1) + .build() + .consumer() + .id("consumer-2") + .partitionId(0) + .build() + .build() + .build() + .member("memberId-2") + .assignment() + .topic("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(1) + .build() + .consumer() + .id("consumer-2") + .partitionId(0) + .build() + .build() + .build() + .build()} +write flush + +read ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .consumer() + .id("consumer-2") + .partitionId(1) + .build() + .build() + .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/partition.assignment/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/partition.assignment/server.rpt new file mode 100644 index 0000000000..0c01fb3d1e --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/partition.assignment/server.rpt @@ -0,0 +1,120 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .members("memberId-2", kafka:memberMetadata() + .consumerId("consumer-2") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +read ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(1) + .build() + .consumer() + .id("consumer-2") + .partitionId(0) + .build() + .build() + .build() + .member("memberId-2") + .assignment() + .topic("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(1) + .build() + .consumer() + .id("consumer-2") + .partitionId(0) + .build() + .build() + .build() + .build()} + +write ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .consumer() + .id("consumer-2") + .partitionId(1) + .build() + .build() + .build()} +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/reassign.new.topic/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/reassign.new.topic/client.rpt new file mode 100644 index 0000000000..f1b7fa3a53 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/reassign.new.topic/client.rpt @@ -0,0 +1,183 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +write ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} +write flush + +read ${kafka:topicAssignment() + .topic() + .id("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .topic("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build()) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .topic("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build()) + .build() + .build()} + +write ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .assignment() + .topic("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build() + .build() + .build()} +write flush + +read ${kafka:topicAssignment() + .topic() + .id("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .topic() + .id("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build() + .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/reassign.new.topic/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/reassign.new.topic/server.rpt new file mode 100644 index 0000000000..e7843e06a0 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/reassign.new.topic/server.rpt @@ -0,0 +1,188 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +read ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} + +write ${kafka:topicAssignment() + .topic() + .id("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build()} +write flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .topic("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build()) + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .topic("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build()) + .build() + .build()} + +read ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .assignment() + .topic("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build() + .build() + .build()} + +write ${kafka:topicAssignment() + .topic() + .id("test-1") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .topic() + .id("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build() + .build()} +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader.in.parallel/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader.in.parallel/client.rpt new file mode 100644 index 0000000000..3349b8fd90 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader.in.parallel/client.rpt @@ -0,0 +1,72 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read notify ROUTED_FIRST_GROUP + +write aborted + +connect await ROUTED_FIRST_GROUP "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader.in.parallel/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader.in.parallel/server.rpt new file mode 100644 index 0000000000..e6b22e881a --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader.in.parallel/server.rpt @@ -0,0 +1,73 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read abort + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader/client.rpt new file mode 100644 index 0000000000..be863d5e6f --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader/client.rpt @@ -0,0 +1,95 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty + +read notify ROUTED_BROKER_SERVER + +write aborted + +connect await ROUTED_BROKER_SERVER "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader/server.rpt new file mode 100644 index 0000000000..63f3642b46 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander.migrate.leader/server.rpt @@ -0,0 +1,97 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush + +read abort + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander/client.rpt new file mode 100644 index 0000000000..d53487e538 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander/client.rpt @@ -0,0 +1,73 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty + +write advise zilla:flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .members("memberId-2") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty + +write close +read closed diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander/server.rpt new file mode 100644 index 0000000000..ca3b929e93 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.highlander/server.rpt @@ -0,0 +1,77 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush + +read advised zilla:flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .members("memberId-2") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty + +read closed +write close diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.unknown/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.unknown/client.rpt new file mode 100644 index 0000000000..a6a92ea2ad --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.unknown/client.rpt @@ -0,0 +1,70 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("unknown") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("unknown") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty + +read notify ROUTED_BROKER_SERVER + +connect await ROUTED_BROKER_SERVER "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("unknown") + .timeout(45000) + .build() + .build()} + +connect aborted diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.unknown/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.unknown/server.rpt new file mode 100644 index 0000000000..09f08d8a9b --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.protocol.unknown/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("unknown") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("unknown") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush + +rejected diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.sync.group/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.sync.group/client.rpt new file mode 100644 index 0000000000..6937ab1880 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.sync.group/client.rpt @@ -0,0 +1,65 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.sync.group/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.sync.group/server.rpt new file mode 100644 index 0000000000..5ca156ca20 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/group/rebalance.sync.group/server.rpt @@ -0,0 +1,69 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(45000) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("test") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1") + .build() + .build()} + +read zilla:data.empty + +write zilla:data.empty +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/client.rpt index 46b8645895..bee1c37b8a 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/client.rpt @@ -38,6 +38,7 @@ connected read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .progress(1, 2, 2, 2) .build() @@ -57,6 +58,7 @@ read "Hello, world #A5" write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .capabilities("FETCH_ONLY") .filter() .headers("header3") diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/server.rpt index 131b4661c7..0662c289a2 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.change/server.rpt @@ -43,6 +43,7 @@ connected write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .progress(1, 2, 2, 2) .build() @@ -64,6 +65,7 @@ write flush read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .filter() .headers("header3") .sequence("one") diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/client.rpt index 65797fa317..95bb8dc375 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/client.rpt @@ -46,6 +46,7 @@ read "Hello, world #A1" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/server.rpt index e6aef8b810..646925b42c 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.header.with.compaction/server.rpt @@ -51,6 +51,7 @@ write "Hello, world #A1" write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} @@ -102,4 +103,4 @@ write zilla:data.ext ${kafka:dataEx() .header("header2", "value2") .build() .build()} -write "Hello, world #A4" \ No newline at end of file +write "Hello, world #A4" diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/client.rpt index 979c34e4c9..3f68ef3c90 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/client.rpt @@ -83,6 +83,7 @@ read notify RECEIVED_MESSAGE_B2 read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 1, 2) .progress(1, 3, 1, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/server.rpt index 0a10a9bbb4..edd7106c28 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none.read.uncommitted/server.rpt @@ -92,6 +92,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 1, 2) .progress(1, 3, 1, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/client.rpt index be72e1a5a0..593b4fc303 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/client.rpt @@ -82,6 +82,7 @@ read notify RECEIVED_MESSAGE_B2 read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 2, 2) .progress(1, 3, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/server.rpt index 592b71500c..99dc1173f7 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.none/server.rpt @@ -91,6 +91,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 2, 2) .progress(1, 3, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/client.rpt index 2996614512..c178993714 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/client.rpt @@ -43,6 +43,7 @@ read zilla:begin.ext ${kafka:matchBeginEx() read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .progress(1, 2, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/server.rpt index 061d4156ab..bd995750f6 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.filter.sync/server.rpt @@ -49,6 +49,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .progress(1, 2, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/client.rpt index ab1d6d8a79..70956daee5 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/client.rpt @@ -83,6 +83,7 @@ read notify RECEIVED_MESSAGE_B2 read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 2, 2) .progress(1, 3, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/server.rpt index c19fa6f57c..66873f85e8 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.isolation.read.committed/server.rpt @@ -92,6 +92,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 2, 2) .progress(1, 3, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/client.rpt index dea36332fb..1a4b4e8acb 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/client.rpt @@ -74,6 +74,7 @@ read "Hello, world #B2" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 2, 2) .progress(1, 3, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/server.rpt index 6eb28b40cb..9b31a8b5de 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.fetch.message.values/server.rpt @@ -87,6 +87,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 3, 2, 2) .progress(1, 3, 2, 2) .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.fetch.message.value/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.fetch.message.value/client.rpt new file mode 100644 index 0000000000..cb654e6997 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.fetch.message.value/client.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("test") + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .partition(0, 1) + .partition(1, 1) + .partition(-1, 1) + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .partition(0, 1, 2) + .progress(0, 2) + .build() + .build()} +read "Hello, world #A1" + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.fetch.message.value/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.fetch.message.value/server.rpt new file mode 100644 index 0000000000..ee3acc2978 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.fetch.message.value/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("test") + .groupId("client-1") + .consumerId("consumer-1") + .timeout(45000) + .partition(0, 1) + .partition(1, 1) + .partition(-1, 1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .partition(0, 1, 2) + .progress(0, 2) + .build() + .build()} +write "Hello, world #A1" +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.invalid.partition/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.invalid.partition/client.rpt new file mode 100644 index 0000000000..4cfca30fad --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.invalid.partition/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("test") + .groupId("client-1") + .consumerId("consumer-1") + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .key("message-key!") + .build() + .build()} +write "Hello, world #A1" +write flush + + +read zilla:reset.ext ${kafka:resetEx() + .typeId(zilla:id("kafka")) + .error(0) + .consumerId("consumer-2") + .build()} + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.invalid.partition/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.invalid.partition/server.rpt new file mode 100644 index 0000000000..7410a8a73c --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.invalid.partition/server.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("test") + .groupId("client-1") + .consumerId("consumer-1") + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .key("message-key!") + .build() + .build()} +read "Hello, world #A1" + +write zilla:reset.ext ${kafka:resetEx() + .typeId(zilla:id("kafka")) + .error(0) + .consumerId("consumer-2") + .build()} + +read abort diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.message.value/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.message.value/client.rpt new file mode 100644 index 0000000000..0903d5fcf0 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.message.value/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("test") + .groupId("client-1") + .consumerId("consumer-1") + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .key("message-key") + .build() + .build()} +write "Hello, world #A1" +write flush + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.message.value/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.message.value/server.rpt new file mode 100644 index 0000000000..915253a018 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.group.produce.message.value/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("test") + .groupId("client-1") + .consumerId("consumer-1") + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .key("message-key") + .build() + .build()} +read "Hello, world #A1" + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/client.rpt index f8c85d060b..ffb8003d11 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/client.rpt @@ -46,6 +46,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .capabilities("PRODUCE_ONLY") .key("key7") @@ -77,6 +78,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .capabilities("PRODUCE_ONLY") .key("key7") @@ -108,6 +110,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .key("key9") .capabilities("PRODUCE_ONLY") @@ -129,6 +132,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .capabilities("PRODUCE_ONLY") .key("key9") diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/server.rpt index 42d6dc55dd..c5e536ab1f 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic.hashed/server.rpt @@ -43,6 +43,7 @@ read "Hello, world #A1" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .key("key7") .build() @@ -69,6 +70,7 @@ read "Hello, world #A2" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .key("key7") .build() @@ -95,9 +97,10 @@ read "Hello, world #C1" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() - .partition(-1, -1) - .key("key9") - .build() + .fetch() + .partition(-1, -1) + .key("key9") + .build() .build()} read zilla:data.ext ${kafka:matchDataEx() @@ -112,7 +115,8 @@ read "Hello, world #C2" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() - .partition(-1, -1) - .key("key9") - .build() + .fetch() + .partition(-1, -1) + .key("key9") + .build() .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/client.rpt index 5277c6dc7a..d40c360bc3 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/client.rpt @@ -45,6 +45,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .capabilities("PRODUCE_ONLY") .build() @@ -73,6 +74,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .capabilities("PRODUCE_ONLY") .build() @@ -91,6 +93,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .capabilities("PRODUCE_ONLY") .build() @@ -119,6 +122,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .capabilities("PRODUCE_ONLY") .build() diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/server.rpt index 1eca6de001..67ef157d76 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush.dynamic/server.rpt @@ -42,6 +42,7 @@ read "Hello, world #A1" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .build() .build()} @@ -66,6 +67,7 @@ read "Hi, world #C1" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .build() .build()} @@ -81,6 +83,7 @@ read "Hello, world #A2" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .build() .build()} @@ -105,6 +108,7 @@ read "Hi, world #C2" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(-1, -1) .build() .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/client.rpt index 7731d53481..7f787cba3f 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/client.rpt @@ -45,6 +45,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(0, 1) .capabilities("PRODUCE_ONLY") .build() @@ -73,6 +74,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(0, 2) .capabilities("PRODUCE_ONLY") .build() @@ -101,6 +103,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(2, 1) .capabilities("PRODUCE_ONLY") .build() @@ -119,7 +122,8 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(2, 2) .capabilities("PRODUCE_ONLY") .build() - .build()} \ No newline at end of file + .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/server.rpt index 985213206a..96c3563c19 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.flush/server.rpt @@ -42,6 +42,7 @@ read "Hello, world #A1" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(0, 1) .build() .build()} @@ -65,6 +66,7 @@ read "Hello, world #A2" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(0, 2) .build() .build()} @@ -88,6 +90,7 @@ read "Hi, world #C1" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(2, 1) .build() .build()} @@ -103,6 +106,7 @@ read "Hi, world #C2" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .partition(2, 2) .build() .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.message.values.dynamic.hash.key/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.message.values.dynamic.hash.key/client.rpt new file mode 100644 index 0000000000..831b80ab24 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.message.values.dynamic.hash.key/client.rpt @@ -0,0 +1,105 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("test") + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .partition(-1, -1) + .key("a") + .hashKey("key7") + .build() + .build()} +write "Hello, world #A1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .partition(-1, -1) + .key("b") + .hashKey("key8") + .build() + .build()} +write "Hello, world #B1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .partition(-1, -1) + .key("a") + .hashKey("key7") + .build() + .build()} +write "Hello, world #A2" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .partition(-1, -1) + .key("b") + .hashKey("key8") + .build() + .build()} +write "Hello, world #B2" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .partition(-1, -1) + .key("c") + .hashKey("key9") + .build() + .build()} +write "Hello, world #C1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(newTimestamp) + .partition(-1, -1) + .key("c") + .hashKey("key9") + .build() + .build()} +write "Hello, world #C2" +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.message.values.dynamic.hash.key/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.message.values.dynamic.hash.key/server.rpt new file mode 100644 index 0000000000..738cd0235c --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/merged.produce.message.values.dynamic.hash.key/server.rpt @@ -0,0 +1,92 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 16 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("test") + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .partition(-1, -1) + .key("a") + .hashKey("key7") + .build() + .build()} +read "Hello, world #A1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .partition(-1, -1) + .key("b") + .hashKey("key8") + .build() + .build()} +read "Hello, world #B1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .partition(-1, -1) + .key("a") + .hashKey("key7") + .build() + .build()} +read "Hello, world #A2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .partition(-1, -1) + .key("b") + .hashKey("key8") + .build() + .build()} +read "Hello, world #B2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .partition(-1, -1) + .key("c") + .hashKey("key9") + .build() + .build()} +read "Hello, world #C1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .partition(-1, -1) + .key("c") + .hashKey("key9") + .build() + .build()} +read "Hello, world #C2" diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.fetch.message.value/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.fetch.message.value/client.rpt new file mode 100644 index 0000000000..05d9edd9da --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.fetch.message.value/client.rpt @@ -0,0 +1,217 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} + +read notify RECEIVED_CONFIG + +connect await RECEIVED_CONFIG + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .build() + .build()} + + +read notify PARTITION_COUNT_2 + +connect await PARTITION_COUNT_2 + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +write ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} +write flush + +read ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .build() + .build()} + +read notify RECEIVED_CONSUMER + +connect await RECEIVED_CONSUMER + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .fetch() + .topic("test") + .partition(0, -2) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .fetch() + .topic("test") + .partition(0, 1, 2) + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .fetch() + .partition(0, 1, 2) + .build() + .build()} +read "Hello, world #A1" + + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.fetch.message.value/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.fetch.message.value/server.rpt new file mode 100644 index 0000000000..180178cfba --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.fetch.message.value/server.rpt @@ -0,0 +1,214 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} + +accept "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .build() + .build()} +write flush + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +read ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} + +write ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .fetch() + .topic("test") + .partition(0, -2) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .fetch() + .topic("test") + .partition(0, 1, 2) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .fetch() + .timestamp(newTimestamp) + .partition(0, 1, 2) + .build() + .build()} +write "Hello, world #A1" +write flush + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.invalid.partition/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.invalid.partition/client.rpt new file mode 100644 index 0000000000..1acf4ae01b --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.invalid.partition/client.rpt @@ -0,0 +1,222 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} + +read notify RECEIVED_CONFIG + +connect await RECEIVED_CONFIG + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .build() + .build()} +read notify PARTITION_COUNT_2 + +connect await PARTITION_COUNT_2 + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +write ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} +write flush + +read ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .consumer() + .id("consumer-2") + .partitionId(1) + .build() + .build() + .build()} + +read notify RECEIVED_CONSUMER + +connect await RECEIVED_CONSUMER + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + option zilla:affinity 1 + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .deferred(10240 - 8192 + padding) + .timestamp(newTimestamp) + .sequence(1) + .ackMode("LEADER_ONLY") + .build() + .build()} +write ${kafka:randomBytes(10240)} +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.invalid.partition/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.invalid.partition/server.rpt new file mode 100644 index 0000000000..d6cb1fba53 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.invalid.partition/server.rpt @@ -0,0 +1,207 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} +property padding 0 + +accept "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(0) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +read ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} + +write ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .consumer() + .id("consumer-2") + .partitionId(1) + .build() + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.message.value/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.message.value/client.rpt new file mode 100644 index 0000000000..9a9aec1d74 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.message.value/client.rpt @@ -0,0 +1,221 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} + +read notify RECEIVED_CONFIG + +connect await RECEIVED_CONFIG + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .build() + .build()} +read notify PARTITION_COUNT_2 + +connect await PARTITION_COUNT_2 + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(45000) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +write ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} +write flush + +read ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .consumer() + .id("consumer-2") + .partitionId(1) + .build() + .build() + .build()} + +read notify RECEIVED_CONSUMER + +connect await RECEIVED_CONSUMER + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + option zilla:affinity 1 + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("message-key") + .build() + .build()} +write "Hello, world #A1" +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.message.value/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.message.value/server.rpt new file mode 100644 index 0000000000..d5ba82e974 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.group.produce.message.value/server.rpt @@ -0,0 +1,218 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} +property padding 0 + +accept "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(0) + .metadata(kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("memberId-1") + .memberId("memberId-1") + .members("memberId-1", kafka:memberMetadata() + .consumerId("consumer-1") + .topic("test") + .partitionId(0) + .partitionId(1) + .build() + .build()) + .build() + .build()} + +read ${kafka:memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(0) + .partitionId(1) + .consumer() + .id("consumer-1") + .partitionId(0) + .partitionId(1) + .build() + .build() + .build() + .build()} + +write ${kafka:topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("consumer-1") + .partitionId(0) + .build() + .consumer() + .id("consumer-2") + .partitionId(1) + .build() + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} +write flush + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("message-key") + .build() + .build()} +read "Hello, world #A1" diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.produce.message.values.dynamic.hash.key/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.produce.message.values.dynamic.hash.key/client.rpt new file mode 100644 index 0000000000..2b07e51ddb --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.produce.message.values.dynamic.hash.key/client.rpt @@ -0,0 +1,245 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} + +read notify RECEIVED_CONFIG + +connect await RECEIVED_CONFIG + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .partition(2, 3) + .build() + .build()} +read notify PARTITION_COUNT_3 + +connect await PARTITION_COUNT_3 + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + option zilla:affinity 1 + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("a") + .build() + .build()} +write "Hello, world #A1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("a") + .build() + .build()} +write "Hello, world #A2" +write flush + +connect await PARTITION_COUNT_3 + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + option zilla:affinity 2 + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(1) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(1) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("b") + .build() + .build()} +write "Hello, world #B1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("b") + .build() + .build()} +write "Hello, world #B2" +write flush + +connect await PARTITION_COUNT_3 + "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "half-duplex" + option zilla:affinity 3 + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(2) + .build() + .build()} + +connected + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(2) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("c") + .build() + .build()} +write "Hello, world #C1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("c") + .build() + .build()} +write "Hello, world #C2" +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.produce.message.values.dynamic.hash.key/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.produce.message.values.dynamic.hash.key/server.rpt new file mode 100644 index 0000000000..f86249e0dd --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/merged/unmerged.produce.message.values.dynamic.hash.key/server.rpt @@ -0,0 +1,233 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property deltaMillis 0L +property newTimestamp ${kafka:timestamp() + deltaMillis} + +accept "zilla://streams/app1" + option zilla:window 64 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .describe() + .topic("test") + .config("cleanup.policy") + .config("max.message.bytes") + .config("segment.bytes") + .config("segment.index.bytes") + .config("segment.ms") + .config("retention.bytes") + .config("retention.ms") + .config("delete.retention.ms") + .config("min.compaction.lag.ms") + .config("max.compaction.lag.ms") + .config("min.cleanable.dirty.ratio") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .describe() + .config("cleanup.policy", "delete") + .config("max.message.bytes", 1000012) + .config("segment.bytes", 1073741824) + .config("segment.index.bytes", 10485760) + .config("segment.ms", 604800000) + .config("retention.bytes", -1) + .config("retention.ms", 604800000) + .config("delete.retention.ms", 86400000) + .config("min.compaction.lag.ms", 0) + .config("max.compaction.lag.ms", 9223372036854775807) + .config("min.cleanable.dirty.ratio", 0.5) + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("test") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, 1) + .partition(1, 2) + .partition(2, 3) + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(0) + .build() + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("a") + .build() + .build()} +read "Hello, world #A1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("a") + .build() + .build()} +read "Hello, world #A2" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(1) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(1) + .build() + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("b") + .build() + .build()} +read "Hello, world #B1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("b") + .build() + .build()} +read "Hello, world #B2" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(2) + .build() + .build()} + +connected + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .produce() + .topic("test") + .partition(2) + .build() + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("c") + .build() + .build()} +read "Hello, world #C1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .produce() + .timestamp(newTimestamp) + .ackMode("LEADER_ONLY") + .key("c") + .build() + .build()} +read "Hello, world #C2" diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.commit/commit.offset/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.commit/commit.offset/client.rpt new file mode 100644 index 0000000000..e80abbc037 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.commit/commit.offset/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-1") + .topic("test") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .partitionId(0) + .partitionOffset(1) + .build() + .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.commit/commit.offset/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.commit/commit.offset/server.rpt new file mode 100644 index 0000000000..9c7c06b8c2 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.commit/commit.offset/server.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-1") + .topic("test") + .build() + .build()} + +connected + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .partition(0) + .partition(1) + .build() + .build()} +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch/partition.offset/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch/partition.offset/client.rpt new file mode 100644 index 0000000000..ece4511733 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch/partition.offset/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-1") + .topic("test", 0) + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .topic("test", 0, 1) + .build() + .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch/partition.offset/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch/partition.offset/server.rpt new file mode 100644 index 0000000000..cd7d3ce9d0 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/offset.fetch/partition.offset/server.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property serverAddress "zilla://streams/app0" + +accept ${serverAddress} + option zilla:window 8192 + option zilla:transmission "half-duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-1") + .topic("test", 0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .topic("test", 0, 1) + .build() + .build()} +write flush diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/client.sent.write.abort.before.coordinator.response/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/client.sent.write.abort.before.coordinator.response/client.rpt new file mode 100644 index 0000000000..e41fd7e95e --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/client.sent.write.abort.before.coordinator.response/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/client.sent.write.abort.before.coordinator.response/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/client.sent.write.abort.before.coordinator.response/server.rpt new file mode 100644 index 0000000000..92a221ad43 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/client.sent.write.abort.before.coordinator.response/server.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.not.available/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.not.available/client.rpt new file mode 100644 index 0000000000..b303cce4f2 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.not.available/client.rpt @@ -0,0 +1,185 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +read 54 # size + (int:newRequestId) + 0 # throttle time + 15s # no coordinator available + 32s "The coordinator is not available" # error no coordinator available + -1 # coordinator node + 0s # host + -1 # port + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER + +connect await ROUTED_DESCRIBE_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 34 # size + (int:newRequestId) + 0 # throttle time + 79s # member id required + -1 # generated id + 0s # protocol name + 0s # leader id + 10s "memberId-1" # consumer member group id + 0 # members + +write 129 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.not.available/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.not.available/server.rpt new file mode 100644 index 0000000000..6a4ca11754 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.not.available/server.rpt @@ -0,0 +1,175 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 54 # size + ${newRequestId} + 0 # throttle time + 15s # no coordinator available + 32s "The coordinator is not available" # error no coordinator available + -1 # coordinator node + 0s # host + -1 # port + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + + +write 34 # size + ${newRequestId} + 0 # throttle time + 79s # member id required + -1 # generated id + 0s # protocol name + 0s # leader id + 10s "memberId-1" # consumer member group id + 0 # members + +read 129 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.reject.invalid.consumer/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.reject.invalid.consumer/client.rpt new file mode 100644 index 0000000000..13114776fb --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.reject.invalid.consumer/client.rpt @@ -0,0 +1,218 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER + +connect await ROUTED_DESCRIBE_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 24 # size + (int:newRequestId) + 0 # throttle time + 16s # not a coordinator for a consumer + -1 # generated id + 0s # protocol name + 0s # leader id + 0s # not a coordinator for a consumer + 0 # members + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.reject.invalid.consumer/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.reject.invalid.consumer/server.rpt new file mode 100644 index 0000000000..32bdf749d7 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/coordinator.reject.invalid.consumer/server.rpt @@ -0,0 +1,208 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 24 # size + ${newRequestId} + 0 # throttle time + 16s # not a coordinator for a consumer + -1 # generated id + 0s # protocol name + 0s # leader id + 0s # not a coordinator for a consumer + 0 # members + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/ignore.heartbeat.before.handshake/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/ignore.heartbeat.before.handshake/client.rpt new file mode 100644 index 0000000000..1cae9a8eab --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/ignore.heartbeat.before.handshake/client.rpt @@ -0,0 +1,167 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_CLUSTER_SERVER + +connect await ROUTED_CLUSTER_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 34 # size + (int:newRequestId) + 0 # throttle time + 79s # member id required + -1 # generated id + 0s # protocol name + 0s # leader id + 10s "memberId-1" # consumer member group id + 0 # members + +write 129 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/ignore.heartbeat.before.handshake/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/ignore.heartbeat.before.handshake/server.rpt new file mode 100644 index 0000000000..e0c1a8cfa2 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/ignore.heartbeat.before.handshake/server.rpt @@ -0,0 +1,160 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + + +write 34 # size + ${newRequestId} + 0 # throttle time + 79s # member id required + -1 # generated id + 0s # protocol name + 0s # leader id + 10s "memberId-1" # consumer member group id + 0 # members + +read 129 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment + + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader.in.parallel/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader.in.parallel/client.rpt new file mode 100644 index 0000000000..c31cdb5d8a --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader.in.parallel/client.rpt @@ -0,0 +1,175 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER_FIRST + +connect await ROUTED_DESCRIBE_SERVER_FIRST + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 129 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader.in.parallel/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader.in.parallel/server.rpt new file mode 100644 index 0000000000..778f9fabf9 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader.in.parallel/server.rpt @@ -0,0 +1,165 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + + +read 82 # size + 32s # describe configs + 0s # v0 + (int:newRequestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${newRequestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 129 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader/client.rpt new file mode 100644 index 0000000000..c9ab07627c --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader/client.rpt @@ -0,0 +1,193 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER_FIRST + +connect await ROUTED_DESCRIBE_SERVER_FIRST + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment + +write 129 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader/server.rpt new file mode 100644 index 0000000000..c5e9f2aab8 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.migrate.leader/server.rpt @@ -0,0 +1,184 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +read 82 # size + 32s # describe configs + 0s # v0 + (int:newRequestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${newRequestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment + + +read 129 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.unknown.member.id/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.unknown.member.id/client.rpt new file mode 100644 index 0000000000..c6026dc79d --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.unknown.member.id/client.rpt @@ -0,0 +1,167 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER + +connect await ROUTED_DESCRIBE_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 24 # size + (int:newRequestId) + 0 # throttle time + 25s # unknown member id + -1 # generated id + 0s # protocol name + 0s # leader id + 0s # consumer member group id + 0 # members + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.unknown.member.id/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.unknown.member.id/server.rpt new file mode 100644 index 0000000000..0e0d7f4050 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander.unknown.member.id/server.rpt @@ -0,0 +1,158 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + + +write 24 # size + ${newRequestId} + 0 # throttle time + 25s # member id required + -1 # generated id + 0s # protocol name + 0s # leader id + 0s # consumer member group id + 0 # members + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander/client.rpt new file mode 100644 index 0000000000..89b17f863c --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander/client.rpt @@ -0,0 +1,263 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER + +connect await ROUTED_DESCRIBE_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 34 # size + (int:newRequestId) + 0 # throttle time + 79s # member id required + -1 # generated id + 0s # protocol name + 0s # leader id + 10s "memberId-1" # consumer member group id + 0 # members + +write 129 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment + +write 81 # size + 12s # heartbeat + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + +read 10 # size + (int:newRequestId) + 0 # throttle time + 27s # REBALANCE_IN_PROGRESS + +write 129 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + + +read 202 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 2 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + 10s "memberId-2" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 117 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 2 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + 10s "memberId-2" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment + +write 81 # size + 13s # leave group + 3s # v3 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 1 # assignments + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + +read 70 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 1 # assignments + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander/server.rpt new file mode 100644 index 0000000000..efa653a695 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.highlander/server.rpt @@ -0,0 +1,254 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + + +write 34 # size + ${newRequestId} + 0 # throttle time + 79s # member id required + -1 # generated id + 0s # protocol name + 0s # leader id + 10s "memberId-1" # consumer member group id + 0 # members + +read 129 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment + +read 81 # size + 12s # heartbeat + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + +write 10 # size + ${newRequestId} + 0 # throttle time + 27s # REBALANCE_IN_PROGRESS + +read 129 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + + +write 202 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 2 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + 10s "memberId-2" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 117 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 2 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + 10s "memberId-2" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment + +read 81 # size + 13s # leave group + 3s # v3 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 1 # assignments + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + +write 70 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 1 # assignments + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.unknown/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.unknown/client.rpt new file mode 100644 index 0000000000..0c69f2053f --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.unknown/client.rpt @@ -0,0 +1,144 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 #port + + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER + +connect await ROUTED_DESCRIBE_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 116 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 7s "unknown" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + + +read 125 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 7s "unknown" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment + diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.unknown/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.unknown/server.rpt new file mode 100644 index 0000000000..ca7dadf2fb --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.protocol.unknown/server.rpt @@ -0,0 +1,132 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 116 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 7s "unknown" # protocol name + 14 # metadata size + [0..14] # metadata + +write 125 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 7s "unknown" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.sync.group/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.sync.group/client.rpt new file mode 100644 index 0000000000..be91dbfc41 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.sync.group/client.rpt @@ -0,0 +1,193 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER + +connect await ROUTED_DESCRIBE_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 27s # rebalance + 0 # assignment + +write 129 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 4 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 4 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.sync.group/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.sync.group/server.rpt new file mode 100644 index 0000000000..9c62766536 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3/rebalance.sync.group/server.rpt @@ -0,0 +1,183 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4s "none" # error message none + 0 # coordinator node + 9s "localhost" # host + 9092 # port + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +accepted + +connected + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 27s # rebalance + 0 # assignment + +read 129 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 4 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 4 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1/leader/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1/leader/client.rpt new file mode 100644 index 0000000000..61af07c325 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1/leader/client.rpt @@ -0,0 +1,229 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 +property instanceId ${kafka:randomBytes(42)} + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 17 # size + 17s # sasl.handshake + 1s # v1 + ${newRequestId} + -1s # no client id + 5s "PLAIN" # mechanism + +read 17 # size + ${newRequestId} + 0s # no error + 1 # mechanisms + 5s "PLAIN" # PLAIN + +write 32 # size + 36s # sasl.authenticate + 1s # v1 + ${newRequestId} + -1s # no client id + 18 + [0x00] "username" # authentication bytes + [0x00] "password" + +read 20 # size + ${newRequestId} + 0s # no error + -1 + -1s # authentication bytes + 0L # session lifetime + +write 22 # size + 10s # find coordinator + 1s # v1 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # "session" coordinator key + [0x00] # coordinator group type + +read 35 # size + (int:newRequestId) + 0 #throttle time + 0s #no error + 4s "none" #error message none + 0 #coordinator node + 9s "localhost" #host + 9092 #port + + +write 17 # size + 17s # sasl.handshake + 1s # v1 + ${newRequestId} + -1s # no client id + 5s "PLAIN" # mechanism + +read 17 # size + ${newRequestId} + 0s # no error + 1 # mechanisms + 5s "PLAIN" # PLAIN + +write 32 # size + 36s # sasl.authenticate + 1s # v1 + ${newRequestId} + -1s # no client id + 18 + [0x00] "username" # authentication bytes + [0x00] "password" + +read 20 # size + ${newRequestId} + 0s # no error + -1 + -1s # authentication bytes + 0L # session lifetime + +write 82 # size + 32s # describe configs + 0s # v0 + ${newRequestId} + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +read 103 # size + (int:newRequestId) + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + +read notify ROUTED_DESCRIBE_SERVER + +connect await ROUTED_DESCRIBE_SERVER + "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 17 # size + 17s # sasl.handshake + 1s # v1 + ${newRequestId} + -1s # no client id + 5s "PLAIN" # mechanism + +read 17 # size + ${newRequestId} + 0s # no error + 1 # mechanisms + 5s "PLAIN" # PLAIN + +write 32 # size + 36s # sasl.authenticate + 1s # v1 + ${newRequestId} + -1s # no client id + 18 + [0x00] "username" # authentication bytes + [0x00] "password" + +read 20 # size + ${newRequestId} + 0s # no error + -1 + -1s # authentication bytes + 0L # session lifetime + +write 119 # size + 11s # join group + 5s # v5 + ${newRequestId} + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s ${instanceId} # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + ${kafka:randomBytes(14)} # metadata + +read 128 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +write 101 # size + 14s # sync group + 3s # v3 + ${newRequestId} + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +read 14 # size + (int:newRequestId) + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1/leader/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1/leader/server.rpt new file mode 100644 index 0000000000..28a7a331d0 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1/leader/server.rpt @@ -0,0 +1,221 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property instanceId ${kafka:randomBytes(42)} + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 17 # size + 17s # sasl.handshake + 1s # v1 + (int:requestId) + -1s # no client id + 5s "PLAIN" # mechanism + +write 17 # size + ${requestId} + 0s # no error + 1 # mechanisms + 5s "PLAIN" # PLAIN + +read 32 # size + 36s # sasl.authenticate + 1s # v1 + (int:requestId) + -1s # no client id + 18 + [0x00] "username" # authentication bytes + [0x00] "password" + +write 20 # size + ${requestId} + 0s # no error + -1 + -1s # authentication bytes + 0L # session lifetime + +read 22 # size + 10s # find coordinator + 1s # v1 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # "test" coordinator key + [0x00] # coordinator group type + +write 35 # size + ${newRequestId} + 0 #throttle time + 0s #no error + 4s "none" #error message none + 0 #coordinator node + 9s "localhost" #host + 9092 #port + + +read 17 # size + 17s # sasl.handshake + 1s # v1 + (int:requestId) + -1s # no client id + 5s "PLAIN" # mechanism + +write 17 # size + ${requestId} + 0s # no error + 1 # mechanisms + 5s "PLAIN" # PLAIN + +read 32 # size + 36s # sasl.authenticate + 1s # v1 + (int:requestId) + -1s # no client id + 18 + [0x00] "username" # authentication bytes + [0x00] "password" + +write 20 # size + ${requestId} + 0s # no error + -1 + -1s # authentication bytes + 0L # session lifetime + +read 82 # size + 32s # describe configs + 0s # v0 + (int:requestId) + -1s # no client id + 1 # resources + [0x04] # broker resource + 1s "0" # "node" topic + 2 # configs + 28s "group.min.session.timeout.ms" # name + 28s "group.max.session.timeout.ms" # name + +write 103 # size + ${requestId} + 0 + 1 # resources + 0s # no error + -1s # error message + [0x04] # broker resource + 1s "0" # "0" nodeId + 2 # configs + 28s "group.min.session.timeout.ms" # name + 4s "6000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + 28s "group.max.session.timeout.ms" # name + 5s "30000" # value + [0x00] # not read only + [0x00] # not default + [0x00] # not sensitive + + +accepted + +connected + +read 17 # size + 17s # sasl.handshake + 1s # v1 + (int:requestId) + -1s # no client id + 5s "PLAIN" # mechanism + +write 17 # size + ${requestId} + 0s # no error + 1 # mechanisms + 5s "PLAIN" # PLAIN + +read 32 # size + 36s # sasl.authenticate + 1s # v1 + (int:requestId) + -1s # no client id + 18 + [0x00] "username" # authentication bytes + [0x00] "password" + +write 20 # size + ${requestId} + 0s # no error + -1 + -1s # authentication bytes + 0L # session lifetime + +read 119 # size + 11s # join group + 5s # v5 + (int:newRequestId) + 5s "zilla" # client id + 4s "test" # consumer group + 30000 # session timeout + 4000 # rebalance timeout + 0s # consumer group member + 42s [0..42] # group instance id + 8s "consumer" # protocol type + 1 # group protocol + 10s "highlander" # protocol name + 14 # metadata size + [0..14] # metadata + + +write 128 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 3 # generated id + 10s "highlander" # protocol name + 10s "memberId-1" # leader id + 10s "memberId-1" # consumer member group id + 1 # members + 10s "memberId-1" # consumer member group id + 42s ${instanceId} # group instance id + 14 # metadata size + 2s # version + 0 # topics + 0 # userdata + 0 # partitions + +read 101 # size + 14s # sync group + 3s # v3 + (int:newRequestId) + 5s "zilla" # no client id + 4s "test" # consumer group + 3 # generation id + 10s "memberId-1" # consumer member group id + 42s [0..42] # group instance id + 1 # assignments + 10s "memberId-1" # consumer member group id + 0 # metadata + +write 14 # size + ${newRequestId} + 0 # throttle time + 0s # no error + 0 # assignment diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/offset.fetch.v0/topic.offset.info/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/offset.fetch.v0/topic.offset.info/client.rpt new file mode 100644 index 0000000000..98de6cd612 --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/offset.fetch.v0/topic.offset.info/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkConnectWindow 8192 + +property newRequestId ${kafka:newRequestId()} +property fetchWaitMax 500 +property fetchBytesMax 65535 +property partitionBytesMax 8192 + +connect "zilla://streams/net0" + option zilla:window ${networkConnectWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write 38 # size + 9s # offset fetch + 0s # v0 + ${newRequestId} + -1s # no client id + 8s "client-1" # group id + 1 # topics + 4s "test" # "test" topic + 1 # partitions + 0 # partition + +read 34 # size + (int:newRequestId) + 1 # topics + 4s "test" # "test" topic + 1 # partitions + 0 # partition index + 1L # committed offset + -1s # metadata + 0s # no error diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/offset.fetch.v0/topic.offset.info/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/offset.fetch.v0/topic.offset.info/server.rpt new file mode 100644 index 0000000000..842c3ac62f --- /dev/null +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/offset.fetch.v0/topic.offset.info/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property networkAcceptWindow 8192 + +accept "zilla://streams/net0" + option zilla:window ${networkAcceptWindow} + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted + +connected + +read 38 # size + 9s # offset fetch + 0s # v0 + (int:newRequestId) + -1s # no client id + 8s "client-1" # group id + 1 # topics + 4s "test" # "test" topic + 1 # partitions + 0 # partition + +write 34 # size + ${newRequestId} + 1 # topics + 4s "test" # "test" topic + 1 # partitions + 0 # partition index + 1L # committed offset + -1s # metadata + 0s # no error diff --git a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctionsTest.java b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctionsTest.java index 1d74e8eecb..9486983a4f 100644 --- a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctionsTest.java +++ b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctionsTest.java @@ -46,6 +46,7 @@ import io.aklivity.zilla.specs.binding.kafka.internal.types.Array32FW; import io.aklivity.zilla.specs.binding.kafka.internal.types.KafkaAckMode; +import io.aklivity.zilla.specs.binding.kafka.internal.types.KafkaCapabilities; import io.aklivity.zilla.specs.binding.kafka.internal.types.KafkaDeltaFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.KafkaDeltaType; import io.aklivity.zilla.specs.binding.kafka.internal.types.KafkaEvaluation; @@ -56,9 +57,13 @@ import io.aklivity.zilla.specs.binding.kafka.internal.types.KafkaTransactionResult; import io.aklivity.zilla.specs.binding.kafka.internal.types.KafkaValueMatchFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.OctetsFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.rebalance.MemberAssignmentFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.rebalance.TopicAssignmentFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaApi; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaBootstrapBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaConsumerBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaConsumerDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaDescribeBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaDescribeDataExFW; @@ -67,12 +72,18 @@ import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaFetchFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupBeginExFW; -import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupFlushExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaGroupMemberMetadataFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMergedFlushExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMetaBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaMetaDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetCommitBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetCommitDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetFetchBeginExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetFetchDataExFW; +import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaOffsetFetchTopicFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaProduceBeginExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaProduceDataExFW; import io.aklivity.zilla.specs.binding.kafka.internal.types.stream.KafkaProduceFlushExFW; @@ -90,6 +101,80 @@ public void setUp() throws Exception ctx = new ExpressionContext(); } + @Test + public void shouldGenerateMemberMetadata() + { + byte[] build = KafkaFunctions.memberMetadata() + .consumerId("localhost:9092") + .topic("test-1") + .partitionId(0) + .partitionId(1) + .build() + .topic("test-2") + .partitionId(0) + .partitionId(1) + .partitionId(2) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaGroupMemberMetadataFW memberMetadata = + new KafkaGroupMemberMetadataFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals("localhost:9092", memberMetadata.consumerId().asString()); + assertEquals(2, memberMetadata.topics().fieldCount()); + } + + @Test + public void shouldGenerateMemberAssignment() + { + byte[] build = KafkaFunctions.memberAssignment() + .member("memberId-1") + .assignment() + .topic("test") + .partitionId(0) + .consumer() + .id("localhost:9092") + .partitionId(0) + .build() + .build() + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + Array32FW assignments = + new Array32FW<>(new MemberAssignmentFW()).wrap(buffer, 0, buffer.capacity()); + + assignments.forEach(a -> + { + assertEquals("memberId-1", a.memberId().asString()); + }); + } + + @Test + public void shouldGenerateTopicAssignment() + { + byte[] build = KafkaFunctions.topicAssignment() + .topic() + .id("test") + .partitionId(0) + .consumer() + .id("localhost:9092") + .partitionId(0) + .build() + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + Array32FW topics = + new Array32FW<>(new TopicAssignmentFW()).wrap(buffer, 0, buffer.capacity()); + + topics.forEach(t -> + { + assertEquals("test", t.topic().asString()); + }); + } + @Test public void shouldGenerateBootstrapBeginExtension() { @@ -212,6 +297,8 @@ public void shouldGenerateMergedBeginExtension() .merged() .capabilities("PRODUCE_AND_FETCH") .topic("topic") + .groupId("groupId") + .consumerId("consumerId") .partition(0, 1L) .filter() .key("match") @@ -232,6 +319,8 @@ public void shouldGenerateMergedBeginExtension() final KafkaMergedBeginExFW mergedBeginEx = beginEx.merged(); assertEquals("topic", mergedBeginEx.topic().asString()); + assertEquals("groupId", mergedBeginEx.groupId().asString()); + assertEquals("consumerId", mergedBeginEx.consumerId().asString()); assertNotNull(mergedBeginEx.partitions() .matchFirst(p -> p.partitionId() == 0 && p.partitionOffset() == 1L)); @@ -448,6 +537,7 @@ public void shouldGenerateMergedDataExtension() .partition(0, 0L) .progress(0, 1L) .key("match") + .hashKey("hashKey") .header("name", "value") .build() .build(); @@ -485,6 +575,10 @@ public void shouldGenerateMergedDataExtension() .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))) && "value".equals(h.value() .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))))); + + assertEquals("hashKey", mergedDataEx.hashKey() + .value() + .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))); } @Test @@ -863,11 +957,12 @@ public void shouldGenerateMergedDataExtensionWithNullKeyAndNullByteArrayHeaderVa } @Test - public void shouldGenerateMergedFlushExtension() + public void shouldGenerateMergedFetchFlushExtension() { byte[] build = KafkaFunctions.flushEx() .typeId(0x01) .merged() + .fetch() .partition(1, 2) .capabilities("PRODUCE_AND_FETCH") .progress(0, 1L) @@ -887,26 +982,26 @@ public void shouldGenerateMergedFlushExtension() final KafkaMergedFlushExFW mergedFlushEx = flushEx.merged(); final MutableInteger partitionsCount = new MutableInteger(); - mergedFlushEx.progress().forEach(f -> partitionsCount.value++); + mergedFlushEx.fetch().progress().forEach(f -> partitionsCount.value++); assertEquals(1, partitionsCount.value); - assertNotNull(mergedFlushEx.progress() + assertNotNull(mergedFlushEx.fetch().progress() .matchFirst(p -> p.partitionId() == 0 && p.partitionOffset() == 1L)); - assertEquals(mergedFlushEx.key().value().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)), "key"); - assertEquals(mergedFlushEx.partition().partitionId(), 1); - assertEquals(mergedFlushEx.partition().partitionOffset(), 2); + assertEquals(mergedFlushEx.fetch().key().value().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)), "key"); + assertEquals(mergedFlushEx.fetch().partition().partitionId(), 1); + assertEquals(mergedFlushEx.fetch().partition().partitionOffset(), 2); final MutableInteger filterCount = new MutableInteger(); - mergedFlushEx.filters().forEach(f -> filterCount.value++); + mergedFlushEx.fetch().filters().forEach(f -> filterCount.value++); assertEquals(2, filterCount.value); - assertNotNull(mergedFlushEx.filters() + assertNotNull(mergedFlushEx.fetch().filters() .matchFirst(f -> f.conditions() .matchFirst(c -> c.kind() == KEY.value() && "match".equals(c.key() .value() .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)))) != null)); - assertNotNull(mergedFlushEx.filters() + assertNotNull(mergedFlushEx.fetch().filters() .matchFirst(f -> f.conditions() .matchFirst(c -> c.kind() == HEADER.value() && "name".equals(c.header().name() @@ -916,11 +1011,12 @@ public void shouldGenerateMergedFlushExtension() } @Test - public void shouldGenerateMergedFlushExtensionWithStableOffset() + public void shouldGenerateMergedFetchFlushExtensionWithStableOffset() { byte[] build = KafkaFunctions.flushEx() .typeId(0x01) .merged() + .fetch() .partition(0, 1L, 1L) .capabilities("PRODUCE_AND_FETCH") .progress(0, 1L, 1L, 1L) @@ -940,29 +1036,29 @@ public void shouldGenerateMergedFlushExtensionWithStableOffset() final KafkaMergedFlushExFW mergedFlushEx = flushEx.merged(); final MutableInteger partitionsCount = new MutableInteger(); - mergedFlushEx.progress().forEach(f -> partitionsCount.value++); + mergedFlushEx.fetch().progress().forEach(f -> partitionsCount.value++); assertEquals(1, partitionsCount.value); - assertEquals(mergedFlushEx.partition().partitionId(), 0); - assertEquals(mergedFlushEx.partition().partitionOffset(), 1L); - assertEquals(mergedFlushEx.partition().latestOffset(), 1L); + assertEquals(mergedFlushEx.fetch().partition().partitionId(), 0); + assertEquals(mergedFlushEx.fetch().partition().partitionOffset(), 1L); + assertEquals(mergedFlushEx.fetch().partition().latestOffset(), 1L); - assertNotNull(mergedFlushEx.progress() + assertNotNull(mergedFlushEx.fetch().progress() .matchFirst(p -> p.partitionId() == 0 && p.partitionOffset() == 1L && p.stableOffset() == 1L && p.latestOffset() == 1L)); final MutableInteger filterCount = new MutableInteger(); - mergedFlushEx.filters().forEach(f -> filterCount.value++); + mergedFlushEx.fetch().filters().forEach(f -> filterCount.value++); assertEquals(2, filterCount.value); - assertNotNull(mergedFlushEx.filters() + assertNotNull(mergedFlushEx.fetch().filters() .matchFirst(f -> f.conditions() .matchFirst(c -> c.kind() == KEY.value() && "match".equals(c.key() .value() .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)))) != null)); - assertNotNull(mergedFlushEx.filters() + assertNotNull(mergedFlushEx.fetch().filters() .matchFirst(f -> f.conditions() .matchFirst(c -> c.kind() == HEADER.value() && "name".equals(c.header().name() @@ -971,6 +1067,27 @@ public void shouldGenerateMergedFlushExtensionWithStableOffset() .get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)))) != null)); } + @Test + public void shouldGenerateMergedConsumerFlushExtension() + { + byte[] build = KafkaFunctions.flushEx() + .typeId(0x01) + .merged() + .consumer() + .partition(1, 2) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaFlushExFW flushEx = new KafkaFlushExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x1, flushEx.typeId()); + + final KafkaMergedFlushExFW mergedFlushEx = flushEx.merged(); + + assertEquals(mergedFlushEx.consumer().partition().partitionId(), 1); + assertEquals(mergedFlushEx.consumer().partition().partitionOffset(), 2); + } + @Test public void shouldMatchMergedDataExtension() throws Exception { @@ -983,6 +1100,7 @@ public void shouldMatchMergedDataExtension() throws Exception .timestamp(12345678L) .key("match") .header("name", "value") + .hashKey("hashKey") .build() .build(); @@ -996,8 +1114,9 @@ public void shouldMatchMergedDataExtension() throws Exception .progressItem(p -> p.partitionId(0).partitionOffset(1L)) .key(k -> k.length(5) .value(v -> v.set("match".getBytes(UTF_8)))) + .hashKey(k -> k.length(7) + .value(v -> v.set("hashKey".getBytes(UTF_8)))) .delta(d -> d.type(t -> t.set(KafkaDeltaType.NONE))) - .headersItem(h -> h.nameLen(4) .name(n -> n.set("name".getBytes(UTF_8))) .valueLen(5) @@ -1399,6 +1518,7 @@ public void shouldMatchMergedDataExtensionNullKey() throws Exception BytesMatcher matcher = KafkaFunctions.matchDataEx() .merged() .key(null) + .hashKey(null) .build() .build(); @@ -2093,6 +2213,56 @@ public void shouldGenerateFetchFlushExtensionWithLatestOffset() assertEquals(1L, partition.latestOffset()); } + @Test + public void shouldGenerateGroupFlushExtension() + { + byte[] build = KafkaFunctions.flushEx() + .typeId(0x01) + .group() + .leaderId("consumer-1") + .memberId("consumer-2") + .members("memberId-1", "test".getBytes()) + .members("memberId-2", "test".getBytes()) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaFlushExFW flushEx = new KafkaFlushExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, flushEx.typeId()); + + final KafkaGroupFlushExFW groupFlushEx = flushEx.group(); + final String leaderId = groupFlushEx.leaderId().asString(); + final String memberId = groupFlushEx.memberId().asString(); + assertEquals("consumer-1", leaderId); + assertEquals("consumer-2", memberId); + assertEquals(2, groupFlushEx.members().fieldCount()); + } + + @Test + public void shouldGenerateGroupFlushExtensionWithEmptyMetadata() + { + byte[] build = KafkaFunctions.flushEx() + .typeId(0x01) + .group() + .leaderId("consumer-1") + .memberId("consumer-2") + .members("memberId-1") + .members("memberId-2") + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaFlushExFW flushEx = new KafkaFlushExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, flushEx.typeId()); + + final KafkaGroupFlushExFW groupFlushEx = flushEx.group(); + final String leaderId = groupFlushEx.leaderId().asString(); + final String memberId = groupFlushEx.memberId().asString(); + assertEquals("consumer-1", leaderId); + assertEquals("consumer-2", memberId); + assertEquals(2, groupFlushEx.members().fieldCount()); + } + @Test public void shouldMatchFetchDataExtension() throws Exception { @@ -2601,6 +2771,76 @@ public void shouldMatchMergedBeginExtensionTopic() throws Exception assertNotNull(matcher.match(byteBuf)); } + @Test + public void shouldMatchMergedBeginExtensionGroupId() throws Exception + { + BytesMatcher matcher = KafkaFunctions.matchBeginEx() + .merged() + .topic("topic") + .groupId("test") + .build() + .build(); + + ByteBuffer byteBuf = ByteBuffer.allocate(1024); + + new KafkaBeginExFW.Builder() + .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) + .typeId(0x01) + .merged(f -> f + .topic("topic") + .groupId("test") + .partitionsItem(p -> p.partitionId(0).partitionOffset(0L)) + .filtersItem(i -> i + .conditionsItem(c -> c + .key(k -> k + .length(3) + .value(v -> v.set("key".getBytes(UTF_8))))) + .conditionsItem(c -> c + .header(h -> h + .nameLen(4) + .name(n -> n.set("name".getBytes(UTF_8))) + .valueLen(5) + .value(v -> v.set("value".getBytes(UTF_8))))))) + .build(); + + assertNotNull(matcher.match(byteBuf)); + } + + @Test + public void shouldMatchMergedBeginExtensionConsumerId() throws Exception + { + BytesMatcher matcher = KafkaFunctions.matchBeginEx() + .merged() + .topic("topic") + .consumerId("test") + .build() + .build(); + + ByteBuffer byteBuf = ByteBuffer.allocate(1024); + + new KafkaBeginExFW.Builder() + .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) + .typeId(0x01) + .merged(f -> f + .topic("topic") + .consumerId("test") + .partitionsItem(p -> p.partitionId(0).partitionOffset(0L)) + .filtersItem(i -> i + .conditionsItem(c -> c + .key(k -> k + .length(3) + .value(v -> v.set("key".getBytes(UTF_8))))) + .conditionsItem(c -> c + .header(h -> h + .nameLen(4) + .name(n -> n.set("name".getBytes(UTF_8))) + .valueLen(5) + .value(v -> v.set("value".getBytes(UTF_8))))))) + .build(); + + assertNotNull(matcher.match(byteBuf)); + } + @Test public void shouldMatchMergedBeginExtensionPartitions() throws Exception { @@ -3259,6 +3499,21 @@ public void shouldGenerateProduceResetExtension() assertEquals(87, resetEx.error()); } + @Test + public void shouldGenerateResetExtensionWithConsumerId() + { + byte[] build = KafkaFunctions.resetEx() + .typeId(0x01) + .consumerId("consumer-1") + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaResetExFW resetEx = new KafkaResetExFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(0x01, resetEx.typeId()); + assertEquals("consumer-1", resetEx.consumerId().asString()); + } + @Test public void shouldMatchProduceDataExtensionTimestamp() throws Exception @@ -3778,6 +4033,30 @@ public void shouldGenerateMergedBeginExtensionWithHeadersFilter() @Test public void shouldGenerateGroupBeginExtension() + { + byte[] build = KafkaFunctions.beginEx() + .typeId(0x01) + .group() + .groupId("test") + .protocol("roundrobin") + .timeout(10) + .metadata("test".getBytes()) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaBeginExFW beginEx = new KafkaBeginExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, beginEx.typeId()); + assertEquals(KafkaApi.GROUP.value(), beginEx.kind()); + + final KafkaGroupBeginExFW groupBeginEx = beginEx.group(); + assertEquals("test", groupBeginEx.groupId().asString()); + assertEquals("roundrobin", groupBeginEx.protocol().asString()); + assertEquals(10, groupBeginEx.timeout()); + } + + @Test + public void shouldGenerateGroupBeginWithEmptyMetadataExtension() { byte[] build = KafkaFunctions.beginEx() .typeId(0x01) @@ -3799,6 +4078,74 @@ public void shouldGenerateGroupBeginExtension() assertEquals(10, groupBeginEx.timeout()); } + @Test + public void shouldGenerateConsumerBeginExtension() + { + byte[] build = KafkaFunctions.beginEx() + .typeId(0x01) + .consumer() + .groupId("test") + .consumerId("consumer-1") + .timeout(10000) + .topic("topic") + .partition(0) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaBeginExFW beginEx = new KafkaBeginExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, beginEx.typeId()); + assertEquals(KafkaApi.CONSUMER.value(), beginEx.kind()); + + final KafkaConsumerBeginExFW consumerBeginEx = beginEx.consumer(); + assertEquals("test", consumerBeginEx.groupId().asString()); + assertEquals("topic", consumerBeginEx.topic().asString()); + assertEquals(1, consumerBeginEx.partitionIds().fieldCount()); + } + + @Test + public void shouldGenerateOffsetFetchBeginExtension() + { + byte[] build = KafkaFunctions.beginEx() + .typeId(0x01) + .offsetFetch() + .groupId("test") + .topic("topic", 0) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaBeginExFW beginEx = new KafkaBeginExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, beginEx.typeId()); + assertEquals(KafkaApi.OFFSET_FETCH.value(), beginEx.kind()); + + final KafkaOffsetFetchBeginExFW offsetFetchBeginEx = beginEx.offsetFetch(); + KafkaOffsetFetchTopicFW topic = offsetFetchBeginEx.topics() + .matchFirst(t -> t.topic().asString().equals("topic")); + assertEquals(1, topic.partitions().fieldCount()); + } + + @Test + public void shouldGenerateOffsetCommitBeginExtension() + { + byte[] build = KafkaFunctions.beginEx() + .typeId(0x01) + .offsetCommit() + .groupId("test") + .topic("topic") + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaBeginExFW beginEx = new KafkaBeginExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, beginEx.typeId()); + assertEquals(KafkaApi.OFFSET_COMMIT.value(), beginEx.kind()); + + final KafkaOffsetCommitBeginExFW offsetCommitBeginEx = beginEx.offsetCommit(); + assertEquals("test", offsetCommitBeginEx.groupId().asString()); + assertEquals("topic", offsetCommitBeginEx.topic().asString()); + } + @Test public void shouldMatchGroupBeginExtension() throws Exception { @@ -3818,55 +4165,79 @@ public void shouldMatchGroupBeginExtension() throws Exception .group(f -> f .groupId("test") .protocol("roundrobin") - .timeout(10)) + .timeout(10) + .metadataLen("test".length()) + .metadata(m -> m.set("test".getBytes()))) .build(); assertNotNull(matcher.match(byteBuf)); } @Test - public void shouldGenerateGroupDataExtension() + public void shouldGenerateConsumerDataExtension() { byte[] build = KafkaFunctions.dataEx() - .typeId(0x01) - .group() - .leaderId("test1") - .memberId("test2") + .typeId(0x03) + .consumer() + .partition(0) + .consumer() + .id("localhost:9092") + .partition(0) + .build() .build() .build(); DirectBuffer buffer = new UnsafeBuffer(build); KafkaDataExFW dataEx = new KafkaDataExFW().wrap(buffer, 0, buffer.capacity()); - assertEquals(0x01, dataEx.typeId()); - assertEquals(KafkaApi.GROUP.value(), dataEx.kind()); + assertEquals(0x03, dataEx.typeId()); + assertEquals(KafkaApi.CONSUMER.value(), dataEx.kind()); - final KafkaGroupDataExFW groupDataEx = dataEx.group(); - assertEquals("test1", groupDataEx.leaderId().asString()); - assertEquals("test2", groupDataEx.memberId().asString()); + final KafkaConsumerDataExFW consumerDataEx = dataEx.consumer(); + assertTrue(consumerDataEx.partitions().fieldCount() == 1); + assertTrue(consumerDataEx.assignments().fieldCount() == 1); } @Test - public void shouldMatchGroupDataExtension() throws Exception + public void shouldGenerateOffsetFetchDataExtension() { - BytesMatcher matcher = KafkaFunctions.matchDataEx() + byte[] build = KafkaFunctions.dataEx() .typeId(0x01) - .group() - .leaderId("test1") - .memberId("test2") + .offsetFetch() + .topic("test", 0, 1L) .build() .build(); - ByteBuffer byteBuf = ByteBuffer.allocate(1024); + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaDataExFW dataEx = new KafkaDataExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, dataEx.typeId()); + assertEquals(KafkaApi.OFFSET_FETCH.value(), dataEx.kind()); - new KafkaDataExFW.Builder() - .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) + final KafkaOffsetFetchDataExFW offsetFetchDataEx = dataEx.offsetFetch(); + KafkaOffsetFW offset = offsetFetchDataEx.topic().offsets().matchFirst(o -> o.partitionId() == 0); + assertEquals("test", offsetFetchDataEx.topic().topic().asString()); + assertEquals(0, offset.partitionId()); + assertEquals(1L, offset.partitionOffset()); + } + + @Test + public void shouldGenerateOffsetCommitDataExtension() + { + byte[] build = KafkaFunctions.dataEx() .typeId(0x01) - .group(f -> f - .leaderId("test1") - .memberId("test2")) + .offsetCommit() + .partitionId(0) + .partitionOffset(1L) + .build() .build(); - assertNotNull(matcher.match(byteBuf)); + DirectBuffer buffer = new UnsafeBuffer(build); + KafkaDataExFW dataEx = new KafkaDataExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0x01, dataEx.typeId()); + assertEquals(KafkaApi.OFFSET_COMMIT.value(), dataEx.kind()); + + final KafkaOffsetCommitDataExFW offsetCommitDataEx = dataEx.offsetCommit(); + assertEquals(0, offsetCommitDataEx.partitionId()); + assertEquals(1L, offsetCommitDataEx.partitionOffset()); } @Test @@ -4129,21 +4500,25 @@ public void shouldMatchMergedFlushExtension() throws Exception BytesMatcher matcher = KafkaFunctions.matchFlushEx() .typeId(0x01) .merged() - .partition(1, 2) - .progress(0, 1L) - .key("key") - .build() + .fetch() + .partition(1, 2) + .progress(0, 1L) + .capabilities("FETCH_ONLY") + .key("key") + .build() .build(); ByteBuffer byteBuf = ByteBuffer.allocate(1024); new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x01) - .merged(f -> f.partition(p -> p.partitionId(1).partitionOffset(2)) + .merged(f -> f + .fetch(m -> m.partition(p -> p.partitionId(1).partitionOffset(2)) .progressItem(p -> p .partitionId(0) .partitionOffset(1L)) - .key(k -> k.length(3).value(v -> v.set("key".getBytes(UTF_8))))) + .capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)) + .key(k -> k.length(3).value(v -> v.set("key".getBytes(UTF_8)))))) .build(); assertNotNull(matcher.match(byteBuf)); @@ -4155,6 +4530,7 @@ public void shouldMatchMergedFlushExtensionWithLatestOffset() throws Exception BytesMatcher matcher = KafkaFunctions.matchFlushEx() .typeId(0x01) .merged() + .fetch() .partition(0, 1L, 1L) .progress(0, 1L, 1L) .build() @@ -4165,12 +4541,12 @@ public void shouldMatchMergedFlushExtensionWithLatestOffset() throws Exception new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x01) - .merged(f -> - f.partition(p -> p.partitionId(0).partitionOffset(1L).latestOffset(1L)) + .merged(f -> f + .fetch(m -> m.partition(p -> p.partitionId(0).partitionOffset(1L).latestOffset(1L)) .progressItem(p -> p .partitionId(0) .partitionOffset(1L) - .latestOffset(1L))) + .latestOffset(1L)))) .build(); assertNotNull(matcher.match(byteBuf)); @@ -4187,9 +4563,11 @@ public void shouldMatchMergedFlushExtensionTypeId() throws Exception new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x01) - .merged(f -> f.progressItem(p -> p - .partitionId(0) - .partitionOffset(1L))) + .merged(f -> f + .fetch(m -> + m.progressItem(p -> p + .partitionId(0) + .partitionOffset(1L)))) .build(); assertNotNull(matcher.match(byteBuf)); @@ -4200,6 +4578,7 @@ public void shouldMatchMergedFlushExtensionProgress() throws Exception { BytesMatcher matcher = KafkaFunctions.matchFlushEx() .merged() + .fetch() .progress(0, 1L, 1L, 1L) .build() .build(); @@ -4208,11 +4587,12 @@ public void shouldMatchMergedFlushExtensionProgress() throws Exception new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x01) - .merged(f -> f.progressItem(p -> p - .partitionId(0) - .partitionOffset(1L) - .stableOffset(1L) - .latestOffset(1L))) + .merged(f -> f + .fetch(m -> m.progressItem(p -> p + .partitionId(0) + .partitionOffset(1L) + .stableOffset(1L) + .latestOffset(1L)))) .build(); assertNotNull(matcher.match(byteBuf)); @@ -4222,12 +4602,14 @@ public void shouldMatchMergedFlushExtensionProgress() throws Exception public void shouldMatchMergedFlushExtensionFilters() throws Exception { BytesMatcher matcher = KafkaFunctions.matchFlushEx() + .typeId(0x01) .merged() - .filter() - .key("key") - .header("name", "value") + .fetch() + .filter() + .key("key") + .header("name", "value") + .build() .build() - .build() .build(); ByteBuffer byteBuf = ByteBuffer.allocate(1024); @@ -4236,7 +4618,7 @@ public void shouldMatchMergedFlushExtensionFilters() throws Exception .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x01) .merged(f -> f - .filtersItem(i -> i + .fetch(m -> m.filtersItem(i -> i .conditionsItem(c -> c .key(k -> k .length(3) @@ -4247,6 +4629,7 @@ public void shouldMatchMergedFlushExtensionFilters() throws Exception .name(n -> n.set("name".getBytes(UTF_8))) .valueLen(5) .value(v -> v.set("value".getBytes(UTF_8))))))) + ) .build(); assertNotNull(matcher.match(byteBuf)); @@ -4263,9 +4646,10 @@ public void shouldNotMatchMergedFlushExtensionTypeId() throws Exception new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x01) - .merged(f -> f.progressItem(p -> p - .partitionId(0) - .partitionOffset(1L))) + .merged(f -> f + .fetch(m -> m.progressItem(p -> p + .partitionId(0) + .partitionOffset(1L)))) .build(); matcher.match(byteBuf); @@ -4277,17 +4661,19 @@ public void shouldNotMatchMergedFlushExtensionProgress() throws Exception BytesMatcher matcher = KafkaFunctions.matchFlushEx() .typeId(0x01) .merged() - .progress(0, 2L) - .build() + .fetch() + .progress(0, 2L) + .build() .build(); ByteBuffer byteBuf = ByteBuffer.allocate(1024); new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x01) - .merged(f -> f.progressItem(p -> p + .merged(f -> f + .fetch(m -> m.progressItem(p -> p .partitionId(0) - .partitionOffset(1L))) + .partitionOffset(1L)))) .build(); matcher.match(byteBuf); @@ -4522,6 +4908,54 @@ public void shouldNotMatchFetchFlushExtensionWithStableOffset() throws Exception matcher.match(byteBuf); } + @Test + public void shouldMatchGroupFlushExtensionMembers() throws Exception + { + BytesMatcher matcher = KafkaFunctions.matchFlushEx() + .typeId(0x01) + .group() + .leaderId("memberId-1") + .memberId("memberId-2") + .members("memberId-1") + .build() + .build(); + + ByteBuffer byteBuf = ByteBuffer.allocate(1024); + + new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) + .typeId(0x01) + .group(f -> f.leaderId("memberId-1").memberId("memberId-2"). + members(m -> m.item(i -> i.id("memberId-1")))) + .build(); + + assertNotNull(matcher.match(byteBuf)); + } + + @Test + public void shouldMatchGroupFlushExtensionMembersMetadata() throws Exception + { + BytesMatcher matcher = KafkaFunctions.matchFlushEx() + .typeId(0x01) + .group() + .leaderId("memberId-1") + .memberId("memberId-2") + .members("memberId-1", "test") + .build() + .build(); + + ByteBuffer byteBuf = ByteBuffer.allocate(1024); + + new KafkaFlushExFW.Builder().wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) + .typeId(0x01) + .group(f -> f.leaderId("memberId-1").memberId("memberId-2"). + members(m -> m.item(i -> i.id("memberId-1") + .metadataLen("test".length()).metadata(o -> o.set("test".getBytes()))))) + .build(); + + assertNotNull(matcher.match(byteBuf)); + } + + @Test(expected = Exception.class) public void shouldNotMatchFetchFlushExtensionWithLatestOffset() throws Exception { diff --git a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/ConsumerIT.java b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/ConsumerIT.java new file mode 100644 index 0000000000..2f0b411930 --- /dev/null +++ b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/ConsumerIT.java @@ -0,0 +1,56 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.kafka.streams.application; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class ConsumerIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/consumer"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${app}/partition.assignment/client", + "${app}/partition.assignment/server"}) + public void shouldAssignPartition() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/reassign.new.topic/client", + "${app}/reassign.new.topic/server"}) + public void shouldReassignOnNewTopic() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/GroupIT.java b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/GroupIT.java new file mode 100644 index 0000000000..c6551a05f8 --- /dev/null +++ b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/GroupIT.java @@ -0,0 +1,128 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.kafka.streams.application; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class GroupIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/kafka/streams/application/group"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${app}/rebalance.protocol.highlander/client", + "${app}/rebalance.protocol.highlander/server"}) + public void shouldLeaveGroupOnGroupRebalanceError() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/client.sent.write.abort.before.coordinator.response/client", + "${app}/client.sent.write.abort.before.coordinator.response/server"}) + public void shouldHandleClientSentWriteAbortBeforeCoordinatorResponse() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/leader/client", + "${app}/leader/server"}) + public void shouldBecameLeader() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/rebalance.protocol.highlander.migrate.leader/client", + "${app}/rebalance.protocol.highlander.migrate.leader/server"}) + public void shouldRebalanceProtocolHighlanderMigrateLeader() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/rebalance.protocol.highlander.migrate.leader.in.parallel/client", + "${app}/rebalance.protocol.highlander.migrate.leader.in.parallel/server"}) + public void shouldRebalanceProtocolHighlanderMigrateLeaderInParallel() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/rebalance.protocol.unknown/client", + "${app}/rebalance.protocol.unknown/server"}) + public void shouldRejectSecondStreamOnUnknownProtocol() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/ignore.heartbeat.before.handshake/client", + "${app}/ignore.heartbeat.before.handshake/server"}) + public void shouldIgnoreHeartbeatBeforeHandshakeComplete() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/rebalance.sync.group/client", + "${app}/rebalance.sync.group/server"}) + public void shouldHandleRebalanceSyncGroup() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/partition.assignment/client", + "${app}/partition.assignment/server"}) + public void shouldAssignGroupPartition() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/reassign.new.topic/client", + "${app}/reassign.new.topic/server"}) + public void shouldReassignOnNewTopic() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/MergedIT.java b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/MergedIT.java index 2fb3d7ae0f..ad819c9df3 100644 --- a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/MergedIT.java +++ b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/application/MergedIT.java @@ -270,6 +270,15 @@ public void shouldProduceMergedMessageValuesDynamicHashed() throws Exception k3po.finish(); } + @Test + @Specification({ + "${app}/merged.produce.message.values.dynamic.hash.key/client", + "${app}/merged.produce.message.values.dynamic.hash.key/server"}) + public void shouldProduceMergedMessageValuesDynamicHashKey() throws Exception + { + k3po.finish(); + } + @Test @Specification({ "${app}/merged.produce.message.flags.incomplete/client", @@ -489,6 +498,15 @@ public void shouldProduceUnmergedMessageValuesDynamicHashed() throws Exception k3po.finish(); } + @Test + @Specification({ + "${app}/unmerged.produce.message.values.dynamic.hash.key/client", + "${app}/unmerged.produce.message.values.dynamic.hash.key/server"}) + public void shouldProduceUnMergedMessageValuesDynamicHashKey() throws Exception + { + k3po.finish(); + } + @Test @Specification({ "${app}/unmerged.fetch.server.sent.close/client", @@ -629,4 +647,58 @@ public void shouldFetchMergedMessagesWithIsolationReadCommitted() throws Excepti { k3po.finish(); } + + @Test + @Specification({ + "${app}/merged.group.fetch.message.value/client", + "${app}/merged.group.fetch.message.value/server"}) + public void shouldFetchGroupMergedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/unmerged.group.fetch.message.value/client", + "${app}/unmerged.group.fetch.message.value/server"}) + public void shouldFetchGroupUnmergedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/unmerged.group.produce.invalid.partition/client", + "${app}/unmerged.group.produce.invalid.partition/server"}) + public void shouldRejectUnmergedMessageForInvalidPartition() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/merged.group.produce.invalid.partition/client", + "${app}/merged.group.produce.invalid.partition/server"}) + public void shouldRejectMergedMessageForInvalidPartition() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/merged.group.produce.message.value/client", + "${app}/merged.group.produce.message.value/server"}) + public void shouldProduceMergedMergedMessageValue() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/unmerged.group.produce.message.value/client", + "${app}/unmerged.group.produce.message.value/server"}) + public void shouldProduceUnmergedMergedMessageValue() throws Exception + { + k3po.finish(); + } } diff --git a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/network/GroupIT.java b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/network/GroupIT.java new file mode 100644 index 0000000000..61321b9d6d --- /dev/null +++ b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/network/GroupIT.java @@ -0,0 +1,128 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.kafka.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class GroupIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/kafka/streams/network/group.f1.j5.s3.l3.h3"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${net}/rebalance.protocol.highlander/client", + "${net}/rebalance.protocol.highlander/server"}) + public void shouldLeaveGroupOnGroupRebalanceError() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/client.sent.write.abort.before.coordinator.response/client", + "${net}/client.sent.write.abort.before.coordinator.response/server"}) + public void shouldHandleClientSentWriteAbortBeforeCoordinatorResponse() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/coordinator.not.available/client", + "${net}/coordinator.not.available/server"}) + public void shouldHandleCoordinatorNotAvailableError() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/coordinator.reject.invalid.consumer/client", + "${net}/coordinator.reject.invalid.consumer/server"}) + public void shouldHRejectInvalidConsumer() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/rebalance.protocol.highlander.unknown.member.id/client", + "${net}/rebalance.protocol.highlander.unknown.member.id/server"}) + public void shouldRebalanceProtocolHighlanderUnknownMemberId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/rebalance.protocol.highlander.migrate.leader/client", + "${net}/rebalance.protocol.highlander.migrate.leader/server"}) + public void shouldRebalanceProtocolHighlanderMigrateLeader() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/rebalance.protocol.highlander.migrate.leader.in.parallel/client", + "${net}/rebalance.protocol.highlander.migrate.leader.in.parallel/server"}) + public void shouldRebalanceProtocolHighlanderMigrateLeaderInParallel() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/rebalance.protocol.unknown/client", + "${net}/rebalance.protocol.unknown/server"}) + public void shouldRejectSecondStreamOnUnknownProtocol() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/rebalance.sync.group//client", + "${net}/rebalance.sync.group/server"}) + public void shouldHandleRebalanceSyncGroup() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/ignore.heartbeat.before.handshake/client", + "${net}/ignore.heartbeat.before.handshake/server"}) + public void shouldIgnoreHeartbeatBeforeHandshakeComplete() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/network/GroupSaslIT.java b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/network/GroupSaslIT.java new file mode 100644 index 0000000000..dc2c16378c --- /dev/null +++ b/specs/binding-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/kafka/streams/network/GroupSaslIT.java @@ -0,0 +1,49 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.kafka.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + + +public class GroupSaslIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", + "io/aklivity/zilla/specs/binding/kafka/streams/network/group.sasl.f1.j5.s3.l3.h3.handshake.v1"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${net}/leader/client", + "${net}/leader/server"}) + public void shouldBecameLeader() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt-kafka.spec/COPYRIGHT b/specs/binding-mqtt-kafka.spec/COPYRIGHT new file mode 100644 index 0000000000..0cb10b6f62 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/COPYRIGHT @@ -0,0 +1,12 @@ +Copyright ${copyrightYears} Aklivity Inc + +Licensed under the Aklivity Community License (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + https://www.aklivity.io/aklivity-community-license/ + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +WARRANTIES OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. diff --git a/specs/binding-mqtt-kafka.spec/LICENSE b/specs/binding-mqtt-kafka.spec/LICENSE new file mode 100644 index 0000000000..f6abb6327b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/LICENSE @@ -0,0 +1,114 @@ + Aklivity Community License Agreement + Version 1.0 + +This Aklivity Community License Agreement Version 1.0 (the “Agreement”) sets +forth the terms on which Aklivity, Inc. (“Aklivity”) makes available certain +software made available by Aklivity under this Agreement (the “Software”). BY +INSTALLING, DOWNLOADING, ACCESSING, USING OR DISTRIBUTING ANY OF THE SOFTWARE, +YOU AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO +SUCH TERMS AND CONDITIONS, YOU MUST NOT USE THE SOFTWARE. IF YOU ARE RECEIVING +THE SOFTWARE ON BEHALF OF A LEGAL ENTITY, YOU REPRESENT AND WARRANT THAT YOU +HAVE THE ACTUAL AUTHORITY TO AGREE TO THE TERMS AND CONDITIONS OF THIS +AGREEMENT ON BEHALF OF SUCH ENTITY. “Licensee” means you, an individual, or +the entity on whose behalf you are receiving the Software. + + 1. LICENSE GRANT AND CONDITIONS. + + 1.1 License. Subject to the terms and conditions of this Agreement, + Aklivity hereby grants to Licensee a non-exclusive, royalty-free, + worldwide, non-transferable, non-sublicenseable license during the term + of this Agreement to: (a) use the Software; (b) prepare modifications and + derivative works of the Software; (c) distribute the Software (including + without limitation in source code or object code form); and (d) reproduce + copies of the Software (the “License”). Licensee is not granted the + right to, and Licensee shall not, exercise the License for an Excluded + Purpose. For purposes of this Agreement, “Excluded Purpose” means making + available any software-as-a-service, platform-as-a-service, + infrastructure-as-a-service or other similar online service that competes + with Aklivity products or services that provide the Software. + + 1.2 Conditions. In consideration of the License, Licensee’s distribution + of the Software is subject to the following conditions: + + (a) Licensee must cause any Software modified by Licensee to carry + prominent notices stating that Licensee modified the Software. + + (b) On each Software copy, Licensee shall reproduce and not remove or + alter all Aklivity or third party copyright or other proprietary + notices contained in the Software, and Licensee must provide the + notice below with each copy. + + “This software is made available by Aklivity, Inc., under the + terms of the Aklivity Community License Agreement, Version 1.0 + located at http://www.Aklivity.io/Aklivity-community-license. BY + INSTALLING, DOWNLOADING, ACCESSING, USING OR DISTRIBUTING ANY OF + THE SOFTWARE, YOU AGREE TO THE TERMS OF SUCH LICENSE AGREEMENT.” + + 1.3 Licensee Modifications. Licensee may add its own copyright notices + to modifications made by Licensee and may provide additional or different + license terms and conditions for use, reproduction, or distribution of + Licensee’s modifications. While redistributing the Software or + modifications thereof, Licensee may choose to offer, for a fee or free of + charge, support, warranty, indemnity, or other obligations. Licensee, and + not Aklivity, will be responsible for any such obligations. + + 1.4 No Sublicensing. The License does not include the right to + sublicense the Software, however, each recipient to which Licensee + provides the Software may exercise the Licenses so long as such recipient + agrees to the terms and conditions of this Agreement. + + 2. TERM AND TERMINATION. This Agreement will continue unless and until + earlier terminated as set forth herein. If Licensee breaches any of its + conditions or obligations under this Agreement, this Agreement will + terminate automatically and the License will terminate automatically and + permanently. + + 3. INTELLECTUAL PROPERTY. As between the parties, Aklivity will retain all + right, title, and interest in the Software, and all intellectual property + rights therein. Aklivity hereby reserves all rights not expressly granted + to Licensee in this Agreement. Aklivity hereby reserves all rights in its + trademarks and service marks, and no licenses therein are granted in this + Agreement. + + 4. DISCLAIMER. Aklivity HEREBY DISCLAIMS ANY AND ALL WARRANTIES AND + CONDITIONS, EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, AND SPECIFICALLY + DISCLAIMS ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR + PURPOSE, WITH RESPECT TO THE SOFTWARE. + + 5. LIMITATION OF LIABILITY. Aklivity WILL NOT BE LIABLE FOR ANY DAMAGES OF + ANY KIND, INCLUDING BUT NOT LIMITED TO, LOST PROFITS OR ANY CONSEQUENTIAL, + SPECIAL, INCIDENTAL, INDIRECT, OR DIRECT DAMAGES, HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, ARISING OUT OF THIS AGREEMENT. THE FOREGOING SHALL + APPLY TO THE EXTENT PERMITTED BY APPLICABLE LAW. + + 6.GENERAL. + + 6.1 Governing Law. This Agreement will be governed by and interpreted in + accordance with the laws of the state of California, without reference to + its conflict of laws principles. If Licensee is located within the + United States, all disputes arising out of this Agreement are subject to + the exclusive jurisdiction of courts located in Santa Clara County, + California. USA. If Licensee is located outside of the United States, + any dispute, controversy or claim arising out of or relating to this + Agreement will be referred to and finally determined by arbitration in + accordance with the JAMS International Arbitration Rules. The tribunal + will consist of one arbitrator. The place of arbitration will be Palo + Alto, California. The language to be used in the arbitral proceedings + will be English. Judgment upon the award rendered by the arbitrator may + be entered in any court having jurisdiction thereof. + + 6.2 Assignment. Licensee is not authorized to assign its rights under + this Agreement to any third party. Aklivity may freely assign its rights + under this Agreement to any third party. + + 6.3 Other. This Agreement is the entire agreement between the parties + regarding the subject matter hereof. No amendment or modification of + this Agreement will be valid or binding upon the parties unless made in + writing and signed by the duly authorized representatives of both + parties. In the event that any provision, including without limitation + any condition, of this Agreement is held to be unenforceable, this + Agreement and all licenses and rights granted hereunder will immediately + terminate. Waiver by Aklivity of a breach of any provision of this + Agreement or the failure by Aklivity to exercise any right hereunder + will not be construed as a waiver of any subsequent breach of that right + or as a waiver of any other right. \ No newline at end of file diff --git a/specs/binding-mqtt-kafka.spec/NOTICE b/specs/binding-mqtt-kafka.spec/NOTICE new file mode 100644 index 0000000000..ba1e058bae --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/NOTICE @@ -0,0 +1,21 @@ +Licensed under the Aklivity Community License (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + https://www.aklivity.io/aklivity-community-license/ + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +WARRANTIES OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +This project includes: + agrona under The Apache License, Version 2.0 + ICU4J under Unicode/ICU License + Jakarta JSON Processing API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception + org.leadpony.justify under The Apache Software License, Version 2.0 + zilla::specs::binding-kafka.spec under The Apache Software License, Version 2.0 + zilla::specs::binding-mqtt.spec under The Apache Software License, Version 2.0 + zilla::specs::binding-proxy.spec under The Apache Software License, Version 2.0 + zilla::specs::engine.spec under The Apache Software License, Version 2.0 + diff --git a/specs/binding-mqtt-kafka.spec/NOTICE.template b/specs/binding-mqtt-kafka.spec/NOTICE.template new file mode 100644 index 0000000000..209ca12f74 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/NOTICE.template @@ -0,0 +1,13 @@ +Licensed under the Aklivity Community License (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + https://www.aklivity.io/aklivity-community-license/ + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +WARRANTIES OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +This project includes: +#GENERATED_NOTICES# diff --git a/incubator/binding-mqtt/mvnw b/specs/binding-mqtt-kafka.spec/mvnw similarity index 100% rename from incubator/binding-mqtt/mvnw rename to specs/binding-mqtt-kafka.spec/mvnw diff --git a/incubator/binding-mqtt/mvnw.cmd b/specs/binding-mqtt-kafka.spec/mvnw.cmd similarity index 100% rename from incubator/binding-mqtt/mvnw.cmd rename to specs/binding-mqtt-kafka.spec/mvnw.cmd diff --git a/specs/binding-mqtt-kafka.spec/pom.xml b/specs/binding-mqtt-kafka.spec/pom.xml new file mode 100644 index 0000000000..dbb6a9ef2b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/pom.xml @@ -0,0 +1,171 @@ + + + + 4.0.0 + + io.aklivity.zilla + specs + 0.9.52 + ../pom.xml + + + binding-mqtt-kafka.spec + zilla::specs::binding-mqtt-kafka.spec + + + + Aklivity Community License Agreement + https://www.aklivity.io/aklivity-community-license/ + repo + + + + + 11 + 11 + 1.00 + 0 + + + + + org.kaazing + k3po.lang + provided + + + ${project.groupId} + engine.spec + ${project.version} + + + ${project.groupId} + binding-mqtt.spec + ${project.version} + + + ${project.groupId} + binding-kafka.spec + ${project.version} + + + junit + junit + test + + + org.kaazing + k3po.junit + test + + + org.hamcrest + hamcrest-library + test + + + + + + + src/main/resources + + + src/main/scripts + + + + + + org.jasig.maven + maven-notice-plugin + + + ${project.groupId} + flyweight-maven-plugin + ${project.version} + + core mqtt kafka + io.aklivity.zilla.specs.binding.mqtt.kafka.internal.types + + + + + validate + generate + + + + + + com.mycila + license-maven-plugin + + + maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.moditect + moditect-maven-plugin + + + org.kaazing + k3po-maven-plugin + + + ${project.groupId} + engine + ${project.version} + test-jar + + + ${project.groupId} + engine + ${project.version} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.jacoco + jacoco-maven-plugin + + + io/aklivity/zilla/specs/binding/mqtt/kafka/internal/types/**/*.class + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + ${jacoco.coverage.ratio} + + + CLASS + MISSEDCOUNT + ${jacoco.missed.count} + + + + + + + + + diff --git a/incubator/binding-mqtt-kafka.spec/src/main/moditect/module-info.java b/specs/binding-mqtt-kafka.spec/src/main/moditect/module-info.java similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/moditect/module-info.java rename to specs/binding-mqtt-kafka.spec/src/main/moditect/module-info.java diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.options.yaml b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.options.yaml new file mode 100644 index 0000000000..58c7456463 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.options.yaml @@ -0,0 +1,27 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +--- +name: test +bindings: + mqtt0: + type: mqtt-kafka + kind: proxy + options: + topics: + sessions: sessions + messages: messages + retained: retained + exit: kafka0 diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.when.capabilities.with.kafka.topic.yaml b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.when.capabilities.with.kafka.topic.yaml similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.when.capabilities.with.kafka.topic.yaml rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.when.capabilities.with.kafka.topic.yaml diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.yaml b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.yaml similarity index 80% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.yaml rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.yaml index 0bd125e0fb..1a9197f8c0 100644 --- a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.yaml +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/config/proxy.yaml @@ -19,4 +19,10 @@ bindings: mqtt0: type: mqtt-kafka kind: proxy + options: + server: mqtt-1.example.com:1883 + topics: + sessions: mqtt-sessions + messages: mqtt-messages + retained: mqtt-retained exit: kafka0 diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json new file mode 100644 index 0000000000..e49e47ccde --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json @@ -0,0 +1,97 @@ +[ + { + "op": "add", + "path": "/$defs/binding/properties/type/enum/-", + "value": "mqtt-kafka" + }, + { + "op": "add", + "path": "/$defs/binding/allOf/-", + "value": + { + "if": + { + "properties": + { + "type": + { + "const": "mqtt-kafka" + } + } + }, + "then": + { + "properties": + { + "type": + { + "const": "mqtt-kafka" + }, + "kind": + { + "enum": [ "proxy" ] + }, + "vault": false, + "options": + { + "properties": + { + "server": + { + "title": "Server Reference", + "type": "string" + }, + "topics": + { + "title": "Topics", + "type": "object", + "properties": + { + "sessions": + { + "title": "Kafka Sessions Topic", + "type": "string" + }, + "messages": + { + "title": "Kafka Messages Topic", + "type": "string" + }, + "retained": + { + "title": "Kafka Retained Topic", + "type": "string" + }, + "additionalProperties": false + }, + "required": + [ + "sessions", + "retained", + "messages" + ], + "additionalProperties": false + } + }, + "required": + [ + "topics" + ], + "additionalProperties": false + }, + "routes": false + }, + "anyOf": + [ + { + "required": + [ + "exit", + "options" + ] + } + ] + } + } + } +] diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/client.rpt new file mode 100644 index 0000000000..4583aba9af --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/server.rpt new file mode 100644 index 0000000000..0ac8dd20c6 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.abort/server.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/client.rpt new file mode 100644 index 0000000000..7e509d96a0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/server.rpt new file mode 100644 index 0000000000..6b7e4b4dd1 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.client.sent.reset/server.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/client.rpt new file mode 100644 index 0000000000..dcfcdff404 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .build() + .build()} + +write zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/server.rpt new file mode 100644 index 0000000000..06ae32f42e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.empty.message/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .build() + .build()} + +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.clients/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.clients/client.rpt new file mode 100644 index 0000000000..f3fe1188d3 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.clients/client.rpt @@ -0,0 +1,147 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write notify CLIENT1_CONNECTED +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" +write flush + + +connect await CLIENT1_CONNECTED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client-2") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client-2") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client-2") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.clients/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.clients/server.rpt new file mode 100644 index 0000000000..31d90ff103 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.clients/server.rpt @@ -0,0 +1,139 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client-2") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client-2") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client-2") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/client.rpt new file mode 100644 index 0000000000..75c0a41415 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/client.rpt @@ -0,0 +1,80 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message1" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/server.rpt new file mode 100644 index 0000000000..6219c1242b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.multiple.messages/server.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message1" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" \ No newline at end of file diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message.changed.topic.name/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message.changed.topic.name/client.rpt new file mode 100644 index 0000000000..b07afe10ea --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message.changed.topic.name/client.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:content-type", "message") + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "messages") + .header("zilla:reply-key", "sensor/one") + .header("zilla:reply-filter", "sensor") + .header("zilla:reply-filter", "one") + .header("zilla:correlation-id", "info") + .build() + .build()} +write "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message.changed.topic.name/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message.changed.topic.name/server.rpt new file mode 100644 index 0000000000..086835619b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message.changed.topic.name/server.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:content-type", "message") + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "messages") + .header("zilla:reply-key", "sensor/one") + .header("zilla:reply-filter", "sensor") + .header("zilla:reply-filter", "one") + .header("zilla:correlation-id", "info") + .build() + .build()} + + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/client.rpt new file mode 100644 index 0000000000..e26510e240 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/client.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:content-type", "message") + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "mqtt-messages") + .header("zilla:reply-key", "sensor/one") + .header("zilla:reply-filter", "sensor") + .header("zilla:reply-filter", "one") + .header("zilla:correlation-id", "info") + .build() + .build()} + + +write "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/server.rpt new file mode 100644 index 0000000000..29c47e3469 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.one.message/server.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:content-type", "message") + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "mqtt-messages") + .header("zilla:reply-key", "sensor/one") + .header("zilla:reply-filter", "sensor") + .header("zilla:reply-filter", "one") + .header("zilla:correlation-id", "info") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.abort/client.rpt new file mode 100644 index 0000000000..e2e758ab9b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.abort/client.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write notify MESSAGES_DONE + +connect await MESSAGES_DONE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.abort/server.rpt new file mode 100644 index 0000000000..d36d277fcc --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.abort/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.data/client.rpt new file mode 100644 index 0000000000..9db3b8a094 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.data/client.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + + +write notify MESSAGES_DONE + +connect await MESSAGES_DONE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read zilla:data.empty + +read abort + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.data/server.rpt new file mode 100644 index 0000000000..cb7cccd4cc --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.data/server.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +write zilla:data.empty + +write aborted + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/client.rpt new file mode 100644 index 0000000000..812b524ed5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write notify MESSAGES_DONE + + +connect await MESSAGES_DONE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/server.rpt new file mode 100644 index 0000000000..78c5c9d6d4 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write advise zilla:flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.reset/client.rpt new file mode 100644 index 0000000000..0b15c9f057 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.reset/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write notify MESSAGES_DONE + +connect await MESSAGES_DONE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write aborted + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.reset/server.rpt new file mode 100644 index 0000000000..8daa57e977 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.reset/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained/client.rpt new file mode 100644 index 0000000000..c4be97bfc6 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained/client.rpt @@ -0,0 +1,113 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" + +write notify MESSAGE_DELIVERED + +connect await MESSAGE_DELIVERED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write advise zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained/server.rpt new file mode 100644 index 0000000000..17da157dac --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained/server.rpt @@ -0,0 +1,113 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read advised zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/client.rpt new file mode 100644 index 0000000000..88622410a9 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/server.rpt new file mode 100644 index 0000000000..e21a1bdb56 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.abort/server.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/client.rpt new file mode 100644 index 0000000000..ef71447f20 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/client.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read zilla:data.empty + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/server.rpt new file mode 100644 index 0000000000..f2a6da9f44 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.data/server.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +write zilla:data.empty + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt new file mode 100644 index 0000000000..ef6ea2280d --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt new file mode 100644 index 0000000000..fb4be6ab02 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/client.rpt new file mode 100644 index 0000000000..564216eb9d --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/server.rpt new file mode 100644 index 0000000000..9fe018d660 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.reset/server.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/client.rpt new file mode 100644 index 0000000000..587bea6745 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/client.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensors/1") + .header("zilla:filter", "sensors") + .header("zilla:filter", "1") + .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") + .header("zilla:format", "TEXT") + .header("row1", "1") + .header("row2", "2") + .build() + .build()} +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/server.rpt new file mode 100644 index 0000000000..ee889e8d1b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.distinct/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensors/1") + .header("zilla:filter", "sensors") + .header("zilla:filter", "1") + .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") + .header("zilla:format", "TEXT") + .header("row1", "1") + .header("row2", "2") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/client.rpt new file mode 100644 index 0000000000..77f5183002 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensors/1") + .header("zilla:filter", "sensors") + .header("zilla:filter", "1") + .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") + .header("zilla:format", "TEXT") + .header("row1", "1") + .header("row1", "2") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/server.rpt new file mode 100644 index 0000000000..567ae9bd64 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.properties.repeated/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensors/1") + .header("zilla:filter", "sensors") + .header("zilla:filter", "1") + .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") + .header("zilla:format", "TEXT") + .header("row1", "1") + .header("row1", "2") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/client.rpt new file mode 100644 index 0000000000..e5c66df5de --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/client.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensors/1") + .header("zilla:filter", "sensors") + .header("zilla:filter", "1") + .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") + .header("zilla:format", "TEXT") + .header("row", "1") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/server.rpt new file mode 100644 index 0000000000..89a6ce7b6b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.with.user.property/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensors/1") + .header("zilla:filter", "sensors") + .header("zilla:filter", "1") + .header("zilla:local", "755452d5-e2ef-4113-b9c6-2f53de96fd76") + .header("zilla:format", "TEXT") + .header("row", "1") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.expire.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.expire.session.state/client.rpt new file mode 100644 index 0000000000..8506d5fce5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.expire.session.state/client.rpt @@ -0,0 +1,262 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .hashKey("client-1") + .build() + .build()} +write flush + + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER + +write zilla:data.empty +write flush + +write abort + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# no will signals +# no session state +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +write abort +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.expire.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.expire.session.state/server.rpt new file mode 100644 index 0000000000..ef9663a613 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.expire.session.state/server.rpt @@ -0,0 +1,269 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify SIGNAL_STREAM_STARTED + +write await RECEIVED_EXPIRY_CANCELLATION_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write await RECEIVED_EXPIRE_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +# expiry signal for client-1, expire at (now + delay) +write await RECEIVED_EXPIRE_AT_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +# cleanup session state +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .hashKey("client-1") + .build() + .build()} +read zilla:data.null + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# receive sender-1 migrate signal + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +write flush + +read zilla:data.empty + +read aborted + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_WILL_CANCELLATION_SIGNAL + + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_EXPIRY_CANCELLATION_SIGNAL + +# expiry signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write notify RECEIVED_EXPIRE_LATER_SIGNAL + +# no session state +# no migrate signals +write advise zilla:flush + +# expiry signal for client-1, expire at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +write notify RECEIVED_EXPIRE_AT_SIGNAL + +read aborted +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.reconnect.non.clean.start/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.reconnect.non.clean.start/client.rpt new file mode 100644 index 0000000000..627d7be1ee --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.reconnect.non.clean.start/client.rpt @@ -0,0 +1,373 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write close +read closed + +write notify INIT_MIGRATE_SENT + +connect await INIT_MIGRATE_SENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write notify RECEIVED_LEADER1 + +write zilla:data.empty +write flush + +write abort + + +connect await RECEIVED_LEADER1 + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +write abort +read aborted + +write notify SESSION1_ABORTED + +connect await SESSION1_ABORTED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write abort +read aborted + +write notify SUBSCRIBE1_ABORTED + +connect await SUBSCRIBE1_ABORTED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write notify INIT2_MIGRATE_SENT + +connect await INIT2_MIGRATE_SENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER2 + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER2 + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read advised zilla:flush + +write notify SESSION_STATE2_FINISHED + +connect await SESSION_STATE2_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.reconnect.non.clean.start/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.reconnect.non.clean.start/server.rpt new file mode 100644 index 0000000000..0e1de2bd8e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.abort.reconnect.non.clean.start/server.rpt @@ -0,0 +1,348 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +read aborted +write abort + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +# session expireAt signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +read aborted +write abort + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read aborted +write abort + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write advise zilla:flush + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.cancel.session.expiry/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.cancel.session.expiry/client.rpt new file mode 100644 index 0000000000..a5e991862a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.cancel.session.expiry/client.rpt @@ -0,0 +1,66 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(2000) + .expireAt(expireAt) + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.cancel.session.expiry/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.cancel.session.expiry/server.rpt new file mode 100644 index 0000000000..0973d7b763 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.cancel.session.expiry/server.rpt @@ -0,0 +1,72 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +property delayMillis 2000L +property expireAt ${mqtt:timestamp() + delayMillis} + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(2000) + .expireAt(expireAt) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.sent.reset/client.rpt new file mode 100644 index 0000000000..782fd686d2 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.sent.reset/client.rpt @@ -0,0 +1,153 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INIT_MIGRATE + +write close +read closed + + +connect await SENT_INIT_MIGRATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty + +read abort + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.sent.reset/server.rpt new file mode 100644 index 0000000000..7629a6188f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.sent.reset/server.rpt @@ -0,0 +1,148 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +write aborted + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.takeover/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.takeover/client.rpt new file mode 100644 index 0000000000..e004bc52f0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.takeover/client.rpt @@ -0,0 +1,486 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write close +read closed + +write notify INIT_MIGRATE_CLOSED + +connect await INIT_MIGRATE_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write zilla:data.empty + +write advise zilla:flush + +write notify HEARTBEAT1_SENT + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} +read notify RECEIVED_LEAVE_GROUP_DATA + +write close + + +connect await RECEIVED_LEAVE_GROUP_DATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +# will signal for client-1, deliver at (now + delay) +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(1000) + .build() + .build()} +write flush + +write close +read closed + +write notify SESSION_STATE1_CLOSED + +connect await SESSION_STATE1_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write close +read closed + +write notify SUBSCRIBE1_CLOSED + +connect await SUBSCRIBE1_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write notify FIRST_CLIENT_LEFT + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +write close +read closed + +write notify INIT_MIGRATE2_FINISHED + +connect await INIT_MIGRATE2_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-2") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} + +write zilla:data.empty + +write advise zilla:flush + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-2") + .memberId("consumer-2") + .members("consumer-2") + .build() + .build()} +read notify RECEIVED_LEADER2 + +write zilla:data.empty + + +connect await RECEIVED_LEADER2 + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read advised zilla:flush + +write notify SESSION_STATE2_FINISHED + +connect await SESSION_STATE2_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.takeover/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.takeover/server.rpt new file mode 100644 index 0000000000..0bfb969589 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.client.takeover/server.rpt @@ -0,0 +1,479 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +read advised zilla:flush + +# On the session stream the heartbeat arrives (on the mqtt-sessions merged stream) +read await HEARTBEAT1_SENT + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} +write flush + +# We've realised that we're the leader, but there's another member -> leave + +read closed +write notify FIRST_CLIENT_LEFT +# On the session publish stream, send a heartbeat, that triggers the second connection to heartbeat on the group stream + +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +#We've left the group -> send migrate +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +# will signal for client-1, deliver at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(1000) + .build() + .build()} + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +write notify HEARTBEAT1_SENT + +read await FIRST_CLIENT_LEFT + +#Migrate arrives from the first connection +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-2") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} +write flush + +read zilla:data.empty + +# On the session publish stream, send a heartbeat +read advised zilla:flush + + +# Wait until I receive a data frame, that confirms that I'm the leader +# Once it's confirmed, I can send the CONNACK + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-2") + .memberId("consumer-2") + .members("consumer-2") + .build() + .build()} +write flush + +read zilla:data.empty + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write advise zilla:flush + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client-1") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.close.expire.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.close.expire.session.state/client.rpt new file mode 100644 index 0000000000..4c092b32a4 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.close.expire.session.state/client.rpt @@ -0,0 +1,263 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .hashKey("client-1") + .build() + .build()} +write flush + + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER + +write zilla:data.empty +write flush + + +write close + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# no will signals +# no session state +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.close.expire.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.close.expire.session.state/server.rpt new file mode 100644 index 0000000000..861a9a642b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.close.expire.session.state/server.rpt @@ -0,0 +1,269 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify SIGNAL_STREAM_STARTED + +write await RECEIVED_EXPIRY_CANCELLATION_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write await RECEIVED_EXPIRE_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +# expiry signal for client-1, expire at (now + delay) +write await RECEIVED_EXPIRE_AT_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +# cleanup session state +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .hashKey("client-1") + .build() + .build()} +read zilla:data.null + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# receive sender-1 migrate signal + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +write flush + +read zilla:data.empty + +read closed + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_WILL_CANCELLATION_SIGNAL + + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_EXPIRY_CANCELLATION_SIGNAL + +# expiry signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write notify RECEIVED_EXPIRE_LATER_SIGNAL + +# no session state +# no migrate signals +write advise zilla:flush + +# expiry signal for client-1, expire at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +write notify RECEIVED_EXPIRE_AT_SIGNAL + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.max.session.expiry/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.max.session.expiry/client.rpt new file mode 100644 index 0000000000..cc2993adc1 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.max.session.expiry/client.rpt @@ -0,0 +1,139 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write close +read closed + +write notify INIT_MIGRATE_CLOSED + +connect await INIT_MIGRATE_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(100000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} + +write zilla:data.empty + +write advise zilla:flush + + +connect await INIT_MIGRATE_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.max.session.expiry/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.max.session.expiry/server.rpt new file mode 100644 index 0000000000..37d998bce5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.max.session.expiry/server.rpt @@ -0,0 +1,133 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(100000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(30000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.min.session.expiry/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.min.session.expiry/client.rpt new file mode 100644 index 0000000000..f66932d8cd --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.min.session.expiry/client.rpt @@ -0,0 +1,139 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write close +read closed + +write notify INIT_MIGRATE_CLOSED + +connect await INIT_MIGRATE_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(0) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(2000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} + +write zilla:data.empty + +write advise zilla:flush + + +connect await INIT_MIGRATE_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.min.session.expiry/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.min.session.expiry/server.rpt new file mode 100644 index 0000000000..627ce38229 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.connect.override.min.session.expiry/server.rpt @@ -0,0 +1,133 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(0) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(2000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.exists.clean.start/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.exists.clean.start/client.rpt new file mode 100644 index 0000000000..124979c6a5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.exists.clean.start/client.rpt @@ -0,0 +1,438 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write close +read closed + +write notify INIT_MIGRATE_SENT1 + +connect await INIT_MIGRATE_SENT1 + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} + +write zilla:data.empty + +write advise zilla:flush + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} +read notify RECEIVED_LEAVE_GROUP_SIGNAL + +write close + + +connect await RECEIVED_LEAVE_GROUP_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION2_NOT_LEADER + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +write notify FIRST_CLIENT_LEFT + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(1000) + .build() + .build()} +write flush + +write close +read closed + +write notify SESSION1_CLOSED + +connect await SESSION1_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write close +read closed + +write notify SUBSCRIBE1_CLOSED + +connect await SUBSCRIBE1_CLOSED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +write notify INIT_MIGRATE_SENT2 + +connect await INIT_MIGRATE_SENT2 + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-2") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} + +write zilla:data.empty + +write advise zilla:flush + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-2") + .memberId("consumer-2") + .members("consumer-2") + .build() + .build()} +read notify RECEIVED_LEADER2 + +write zilla:data.empty + + +connect await RECEIVED_LEADER2 + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.exists.clean.start/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.exists.clean.start/server.rpt new file mode 100644 index 0000000000..f42dcde687 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.exists.clean.start/server.rpt @@ -0,0 +1,438 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +# On the session stream the heartbeat arrives (on the mqtt-sessions merged stream) +read advised zilla:flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} +write flush + +# We've realised that we're not the only member -> leave the group + +read closed +write notify FIRST_CLIENT_LEFT +# On the session publish stream, send a heartbeat, that triggers the second connection to heartbeat on the group stream + +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read await SESSION2_NOT_LEADER +#Hearbeat arrives +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +read await FIRST_CLIENT_LEFT + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +# will signal for client-1, deliver at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(1000) + .build() + .build()} + +read closed +write close + + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read await FIRST_CLIENT_LEFT + +#Migrate arrives from the first connection +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-2") + .members("consumer-1") + .members("consumer-2") + .build() + .build()} +write flush +write notify SESSION2_NOT_LEADER + +read zilla:data.empty + +# On the session publish stream, send a heartbeat + +read advised zilla:flush + + +# Wait until I receive a data frame, that confirms that I'm the leader +# Once it's confirmed, I can send the CONNACK + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-2") + .memberId("consumer-2") + .members("consumer-2") + .build() + .build()} +write flush + +read zilla:data.empty + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write advise zilla:flush + +# clear session state, as it's a clean start +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.group.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.group.server.sent.reset/client.rpt new file mode 100644 index 0000000000..54ed18879f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.group.server.sent.reset/client.rpt @@ -0,0 +1,131 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INIT_MIGRATE + +write close +read closed + + +connect await SENT_INIT_MIGRATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER_DATA + +write zilla:data.empty + +read notify CONNACK_TRIGGERED + +connect await RECEIVED_LEADER_DATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +read advised zilla:flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.group.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.group.server.sent.reset/server.rpt new file mode 100644 index 0000000000..baccf1ddd6 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.group.server.sent.reset/server.rpt @@ -0,0 +1,131 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +read await CONNACK_TRIGGERED + +read abort + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +write advise zilla:flush + +write notify CONNACK_TRIGGERED diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.redirect/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.redirect/client.rpt new file mode 100644 index 0000000000..8a99981fdf --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.redirect/client.rpt @@ -0,0 +1,157 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .consumerId("mqtt-1.example.com:1883") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INIT_MIGRATE + +write close +read closed + + +connect await SENT_INIT_MIGRATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER_DATA + +write zilla:data.empty + + +connect await RECEIVED_LEADER_DATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .consumerId("mqtt-1.example.com:1883") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +# session expire later signal for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read zilla:reset.ext ${kafka:resetEx() + .typeId(zilla:id("kafka")) + .consumerId("mqtt-2.example.com:1883") + .build()} + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.redirect/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.redirect/server.rpt new file mode 100644 index 0000000000..21e5089dea --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.redirect/server.rpt @@ -0,0 +1,152 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .consumerId("mqtt-1.example.com:1883") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .consumerId("mqtt-1.example.com:1883") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write zilla:reset.ext ${kafka:resetEx() + .typeId(zilla:id("kafka")) + .consumerId("mqtt-2.example.com:1883") + .build()} +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.server.sent.reset/client.rpt new file mode 100644 index 0000000000..908ebfbfd8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.server.sent.reset/client.rpt @@ -0,0 +1,150 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INIT_MIGRATE + +write close +read closed + +connect await SENT_INIT_MIGRATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.server.sent.reset/server.rpt new file mode 100644 index 0000000000..7254fa625b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.server.sent.reset/server.rpt @@ -0,0 +1,147 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.session.expiry.fragmented/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.session.expiry.fragmented/client.rpt new file mode 100644 index 0000000000..a5e991862a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.session.expiry.fragmented/client.rpt @@ -0,0 +1,66 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(2000) + .expireAt(expireAt) + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.session.expiry.fragmented/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.session.expiry.fragmented/server.rpt new file mode 100644 index 0000000000..92d6b90b1f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.session.expiry.fragmented/server.rpt @@ -0,0 +1,70 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +property delayMillis 2000L +property expireAt ${mqtt:timestamp() + delayMillis} + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +write option zilla:flags "init" +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .header("type", "expiry-signal") + .build() + .build()} +write [0x01 0x07 0x00 0x7a 0x69 0x6c 0x6c 0x61 0x2d 0x31 0x08 0x00 0x63 0x6c 0x69 0x65 0x6e 0x74 0x2d] +write flush + +write option zilla:flags "fin" +write [0x31 0xd0 0x07 0x00 0x00 0xbe 0x35 0x1a 0xa5 0x8a 0x01 0x00 0x00] +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe.via.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe.via.session.state/client.rpt new file mode 100644 index 0000000000..18b3359464 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe.via.session.state/client.rpt @@ -0,0 +1,200 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write notify INIT_MIGRATE_SENT + +connect await INIT_MIGRATE_SENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION_FINISHED + +connect await SESSION_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe.via.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe.via.session.state/server.rpt new file mode 100644 index 0000000000..5bd67d35fd --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe.via.session.state/server.rpt @@ -0,0 +1,195 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write notify SESSION_STATE_SENT + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe/client.rpt new file mode 100644 index 0000000000..3eb35e357b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe/client.rpt @@ -0,0 +1,216 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INIT_MIGRATE + +write close +read closed + + +connect await SENT_INIT_MIGRATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe/server.rpt new file mode 100644 index 0000000000..1457648966 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.subscribe/server.rpt @@ -0,0 +1,212 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# This is the second prerequisite +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.after.subscribe/client.rpt new file mode 100644 index 0000000000..f03445143c --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.after.subscribe/client.rpt @@ -0,0 +1,241 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write notify SESSION1_FINISHED + +connect await SESSION1_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write notify SESSION_FINISHED + +connect await SESSION_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.after.subscribe/server.rpt new file mode 100644 index 0000000000..a66373b56e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.after.subscribe/server.rpt @@ -0,0 +1,234 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .build()} +write flush + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.via.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.via.session.state/client.rpt new file mode 100644 index 0000000000..89ea472605 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.via.session.state/client.rpt @@ -0,0 +1,212 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush + +write notify INIT_MIGRATE_SENT + +connect await INIT_MIGRATE_SENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write notify SESSION1_FINISHED + + +connect await SESSION1_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.via.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.via.session.state/server.rpt new file mode 100644 index 0000000000..3807c05c93 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.unsubscribe.via.session.state/server.rpt @@ -0,0 +1,203 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1") + .build() + .build()} + +write ${mqtt:session() + .build()} +write flush + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will.retain/client.rpt new file mode 100644 index 0000000000..b2ba50fd08 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will.retain/client.rpt @@ -0,0 +1,494 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +read advised zilla:flush +read notify RECEIVED_WILL_SIGNAL_NOT_PRESENT + +write close +read closed + + +connect await RECEIVED_WILL_SIGNAL_NOT_PRESENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER + +write zilla:data.empty + +write abort + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .flags("RETAIN") + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} + +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +write abort +read aborted + + +connect await RECEIVED_WILL_DELIVER_AT_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .flags("RETAIN") + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +read notify RECEIVED_SESSION_WILL_MESSAGE + +write close +read closed + + + +connect await RECEIVED_SESSION_WILL_MESSAGE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "client-1 disconnected abruptly" +write flush + +write close +read closed + + +connect await RECEIVED_SESSION_WILL_MESSAGE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "client-1 disconnected abruptly" +write flush + +write close +read closed + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will.retain/server.rpt new file mode 100644 index 0000000000..5021ae6338 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will.retain/server.rpt @@ -0,0 +1,488 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify WILL_STREAM_STARTED + +write await RECEIVED_WILL_CANCELLATION_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write await RECEIVED_WILL_DELIVER_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +# will signal for client-1, deliver at (now + delay) +write await RECEIVED_WILL_DELIVER_AT_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +# cleanup will message +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read zilla:data.null + +# cleanup will signal +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + + +# non-clean start +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +# no will signals +write advise zilla:flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# receive sender-1 migrate signal + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +write flush + +read zilla:data.empty + +read aborted + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_WILL_CANCELLATION_SIGNAL + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .flags("RETAIN") + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} + +# will signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_LATER_SIGNAL + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +# no session state +# no migrate signals +write advise zilla:flush + +# will signal for client-1, deliver at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_AT_SIGNAL + +# session expireAt signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +read aborted +write abort + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +# send session will message for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .flags("RETAIN") + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +# deliver will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .header("zilla:format", "TEXT") + .build() + .build()} +read "client-1 disconnected abruptly" + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +# deliver will message for client-1 (retained) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .header("zilla:format", "TEXT") + .build() + .build()} +read "client-1 disconnected abruptly" + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will/client.rpt new file mode 100644 index 0000000000..c174f154f0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will/client.rpt @@ -0,0 +1,470 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +read advised zilla:flush +read notify RECEIVED_WILL_SIGNAL_NOT_PRESENT + +write close +read closed + + +connect await RECEIVED_WILL_SIGNAL_NOT_PRESENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER + +write zilla:data.empty + +write abort + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +# no will signals +# no session state +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} + +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +write abort +read aborted + + +connect await RECEIVED_WILL_DELIVER_AT_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} +read notify RECEIVED_SESSION_WILL_MESSAGE + +write close +read closed + + + +connect await RECEIVED_SESSION_WILL_MESSAGE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "mqtt-messages") + .header("zilla:reply-key", "responses/client1") + .header("zilla:reply-filter", "responses") + .header("zilla:reply-filter", "client1") + .header("zilla:correlation-id", "info") + .build() + .build()} + +write "client-1 disconnected abruptly" +write flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will/server.rpt new file mode 100644 index 0000000000..75656273f8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.abort.deliver.will/server.rpt @@ -0,0 +1,467 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify WILL_STREAM_STARTED + +write await RECEIVED_WILL_CANCELLATION_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write await RECEIVED_WILL_DELIVER_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +# will signal for client-1, deliver at (now + delay) +write await RECEIVED_WILL_DELIVER_AT_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +# cleanup will message +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read zilla:data.null + +# cleanup will signal +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + + +# non-clean start +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +# no will signals +write advise zilla:flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# receive sender-1 migrate signal + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} + +read zilla:data.empty + +read aborted + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_WILL_CANCELLATION_SIGNAL + + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} + +# will signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_LATER_SIGNAL + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +# no session state +# no migrate signals +write advise zilla:flush + +# will signal for client-1, deliver at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_AT_SIGNAL + +# session expireAt signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +read aborted +write abort + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +# send session will message for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +# deliver will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "mqtt-messages") + .header("zilla:reply-key", "responses/client1") + .header("zilla:reply-filter", "responses") + .header("zilla:reply-filter", "client1") + .header("zilla:correlation-id", "info") + .build() + .build()} +read "client-1 disconnected abruptly" + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.cancel.delivery/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.cancel.delivery/client.rpt new file mode 100644 index 0000000000..b1e3d9e768 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.cancel.delivery/client.rpt @@ -0,0 +1,131 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(deliverAt) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL +read notify ONE_SECOND_ELAPSED + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + + +connect await RECEIVED_WILL_DELIVER_AT_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +read notify RECEIVED_WILL + +write close +read closed + +connect await RECEIVED_WILL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.cancel.delivery/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.cancel.delivery/server.rpt new file mode 100644 index 0000000000..16e530e395 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.cancel.delivery/server.rpt @@ -0,0 +1,131 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +property delayMillis 2000L +property deliverAt ${mqtt:timestamp() + delayMillis} + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(deliverAt) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write await ONE_SECOND_ELAPSED +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +# send session will message for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +read closed +write close + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.clean.start/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.clean.start/client.rpt new file mode 100644 index 0000000000..9e79635250 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.clean.start/client.rpt @@ -0,0 +1,238 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER + +write zilla:data.empty + +write abort + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(0) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.clean.start/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.clean.start/server.rpt new file mode 100644 index 0000000000..0e20b9315f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.clean.start/server.rpt @@ -0,0 +1,242 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify WILL_STREAM_STARTED + +write await RECEIVED_WILL_DELIVER_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + + +# no will lifetimeId fetch due to clean-start +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# receive sender-1 migrate signal +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# no will cancellation signal due to clean-start + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .delay(0) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} + +# will signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_LATER_SIGNAL + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +# no session state +# no migrate signals +write advise zilla:flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.normal.disconnect/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.normal.disconnect/client.rpt new file mode 100644 index 0000000000..7d5f199a10 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.normal.disconnect/client.rpt @@ -0,0 +1,366 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} +read notify RECEIVED_WILL_SIGNAL + +read advised zilla:flush + +write close +read closed + + +connect await RECEIVED_WILL_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER + +write zilla:data.empty + +write close + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-7ce005a0-ce9d-444d-b14b-2f302d13799d") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(0) + .format("TEXT") + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-7ce005a0-ce9d-444d-b14b-2f302d13799d") + .hashKey("client-1") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.normal.disconnect/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.normal.disconnect/server.rpt new file mode 100644 index 0000000000..7e0fb62e2a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.normal.disconnect/server.rpt @@ -0,0 +1,372 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify WILL_STREAM_STARTED + +write await RECEIVED_WILL_CANCELLATION_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write await RECEIVED_WILL_DELIVER_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write await RECEIVED_WILL_SIGNAL_CLEANUP +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write flush + + +# non-clean start +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +# existing will signal for client-1, use lifetimeId +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} +write flush + +write advise zilla:flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# receive sender-1 migrate signal + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +write flush + +read zilla:data.empty + +read closed + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_WILL_CANCELLATION_SIGNAL + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-7ce005a0-ce9d-444d-b14b-2f302d13799d") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .delay(0) + .format("TEXT") + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} + +# will signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(0) + .deliverAt(-1) + .lifetimeId("7ce005a0-ce9d-444d-b14b-2f302d13799d") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +read notify RECEIVED_WILL_DELIVER_LATER_SIGNAL + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +# no session state +# no migrate signals +write advise zilla:flush + +# cleanup will message +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-7ce005a0-ce9d-444d-b14b-2f302d13799d") + .hashKey("client-1") + .build() + .build()} +read zilla:data.null + +# cleanup will signal +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +write notify RECEIVED_WILL_SIGNAL_CLEANUP + +# session expireAt signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.takeover.deliver.will/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.takeover.deliver.will/client.rpt new file mode 100644 index 0000000000..70ec7a00d8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.takeover.deliver.will/client.rpt @@ -0,0 +1,456 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +read advised zilla:flush +read notify RECEIVED_WILL_SIGNAL_NOT_PRESENT + +write close +read closed + + +connect await RECEIVED_WILL_SIGNAL_NOT_PRESENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER +write zilla:data.empty + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .members("member-2") + .build() + .build()} + +write close + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} + +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write close +read closed + + +connect await RECEIVED_WILL_DELIVER_AT_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +read notify RECEIVED_SESSION_WILL_MESSAGE + +write close +read closed + + + +connect await RECEIVED_SESSION_WILL_MESSAGE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "client-1 disconnected abruptly" +write flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.takeover.deliver.will/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.takeover.deliver.will/server.rpt new file mode 100644 index 0000000000..4ffd495ed4 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.takeover.deliver.will/server.rpt @@ -0,0 +1,460 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify WILL_STREAM_STARTED + +write await RECEIVED_WILL_CANCELLATION_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write await RECEIVED_WILL_DELIVER_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +# will signal for client-1, deliver at (now + delay) +write await RECEIVED_WILL_DELIVER_AT_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +# cleanup will message +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read zilla:data.null + +# cleanup will signal +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + + +# non-clean start +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +# no will signals +write advise zilla:flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# receive sender-1 migrate signal + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +write flush + +read zilla:data.empty + +write await RECEIVED_WILL_DELIVER_LATER_SIGNAL + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .members("member-2") + .build() + .build()} +write flush + +read closed + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_WILL_CANCELLATION_SIGNAL + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} + +# will signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_LATER_SIGNAL + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +# no session state +# no migrate signals +write advise zilla:flush + +# migrate signal +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +# will signal for client-1, deliver at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +# send session will message for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .format("TEXT") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + +# deliver will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("obituaries") + .header("zilla:filter", "obituaries") + .header("zilla:format", "TEXT") + .build() + .build()} +read "client-1 disconnected abruptly" + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.will.id.mismatch.skip.delivery/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.will.id.mismatch.skip.delivery/client.rpt new file mode 100644 index 0000000000..4cea7bf2ac --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.will.id.mismatch.skip.delivery/client.rpt @@ -0,0 +1,402 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +read notify RECEIVED_WILL_DELIVER_AT_SIGNAL + + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +read advised zilla:flush +read notify RECEIVED_WILL_SIGNAL_NOT_PRESENT + +write close +read closed + + +connect await RECEIVED_WILL_SIGNAL_NOT_PRESENT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_INITIAL_MIGRATE_SIGNAL + +write close +read closed + + +connect await SENT_INITIAL_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +read notify RECEIVED_GROUP_MEMBERS_LEADER + +write zilla:data.empty + +write abort + + +connect await RECEIVED_GROUP_MEMBERS_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +read advised zilla:flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} + +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} +write flush + +write abort +read aborted + + +connect await RECEIVED_WILL_DELIVER_AT_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("different willId") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} + +write close +read closed + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.will.id.mismatch.skip.delivery/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.will.id.mismatch.skip.delivery/server.rpt new file mode 100644 index 0000000000..99dbf9f33f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.message.will.id.mismatch.skip.delivery/server.rpt @@ -0,0 +1,403 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected +read notify WILL_STREAM_STARTED + +write await RECEIVED_WILL_CANCELLATION_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +write flush + +write await RECEIVED_WILL_DELIVER_LATER_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + +# will signal for client-1, different willId +write await RECEIVED_WILL_DELIVER_AT_SIGNAL +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .header("type", "will-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} +write flush + + +# non-clean start +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#will-signal") + .build() + .build() + .build()} + +connected + +# no will signals +write advise zilla:flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# receive sender-1 migrate signal + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#migrate") + .hashKey("client-1") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-1") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +connected + +# send group members (leader) +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("member-1") + .memberId("member-1") + .members("member-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# will delivery cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read zilla:data.null +read notify RECEIVED_WILL_CANCELLATION_SIGNAL + +# session expiry cancellation signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +# will message for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} + +# will signal for client-1, deliver later +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .header("type", "will-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(-1) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_LATER_SIGNAL + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("PRODUCE_AND_FETCH") + .filter() + .key("client-1") + .build() + .filter() + .key("client-1#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +# no session state +# no migrate signals +write advise zilla:flush + +# will signal for client-1, deliver at (now + delay) +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-signal") + .hashKey("client-1") + .build() + .build()} +read ${mqtt:sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .deliverAt(2000) + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("d252a6bd-abb5-446a-b0f7-d0a3d8c012e2") + .build() + .build()} + +write notify RECEIVED_WILL_DELIVER_AT_SIGNAL + +# session expireAt signal for client-1 +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#expiry-signal") + .hashKey("client-1") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(1000) + .expireAt(2000) + .build() + .build()} + +read aborted +write abort + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-sessions") + .filter() + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build() + .build()} + +connected + +# send session will message for client-1 +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("client-1#will-1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .delay(1000) + .expiryInterval(15000) + .format("TEXT") + .responseTopic("responses/client1") + .lifetimeId("1e6a1eb5-810a-459d-a12c-a6fa08f228d1") + .willId("different willId") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} +write flush +# willId != willId from the will-signal so we don't send will message + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.abort.reconnect/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.abort.reconnect/client.rpt new file mode 100644 index 0000000000..10c9e5ef9b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.abort.reconnect/client.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read aborted +read notify RECEIVED_ABORT +write abort + +connect await RECEIVED_ABORT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.abort.reconnect/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.abort.reconnect/server.rpt new file mode 100644 index 0000000000..3fc0dc810e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.abort.reconnect/server.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +write abort +read aborted + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.end.reconnect/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.end.reconnect/client.rpt new file mode 100644 index 0000000000..d650829708 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.end.reconnect/client.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read closed +read notify RECEIVED_CLOSE +write close + +connect await RECEIVED_CLOSE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.end.reconnect/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.end.reconnect/server.rpt new file mode 100644 index 0000000000..dc540e79ad --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.end.reconnect/server.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +write close +read closed + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.reset.reconnect/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.reset.reconnect/client.rpt new file mode 100644 index 0000000000..75d681e200 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.reset.reconnect/client.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +write aborted +read notify SENT_RESET + +connect await SENT_RESET + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.reset.reconnect/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.reset.reconnect/server.rpt new file mode 100644 index 0000000000..44c7564630 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/session.will.stream.reset.reconnect/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + +read abort + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .header("type", "will-signal") + .build() + .filter() + .header("type", "expiry-signal") + .build() + .build() + .build()} + +connected + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/client.rpt new file mode 100644 index 0000000000..42febc297e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/server.rpt new file mode 100644 index 0000000000..249f000fd6 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.abort/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/client.rpt new file mode 100644 index 0000000000..74cd335878 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/server.rpt new file mode 100644 index 0000000000..08266fd63d --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.data/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/client.rpt new file mode 100644 index 0000000000..cf90ccb5ae --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/server.rpt new file mode 100644 index 0000000000..33a4cd48c0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.client.sent.reset/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.deferred.filter.change.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.deferred.filter.change.retain/client.rpt new file mode 100644 index 0000000000..b5e058ea9d --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.deferred.filter.change.retain/client.rpt @@ -0,0 +1,238 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + + +connected + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("three") + .build() + .build() + .build() + .build()} + +write notify RETAIN_FINISHED + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" + +write notify MESSAGES_FINISHED + +connect await MESSAGES_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("three") + .build() + .build() + .build() + .build()} + +write notify SECOND_FLUSH_SENT + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(2) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/three") + .header("zilla:filter", "sensor") + .header("zilla:filter", "three") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read advised zilla:flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.deferred.filter.change.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.deferred.filter.change.retain/server.rpt new file mode 100644 index 0000000000..4f5542f2ec --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.deferred.filter.change.retain/server.rpt @@ -0,0 +1,249 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("three") + .build() + .build() + .build() + .build()} + +read await RETAIN_FINISHED + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" +write flush + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write notify FIRST_RETAINED_SENT + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("three") + .build() + .build() + .build() + .build()} +read await SECOND_FLUSH_SENT + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(2) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/three") + .header("zilla:filter", "sensor") + .header("zilla:filter", "three") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write advise zilla:flush + +read closed +write close + +write notify RETAIN_FINISHED diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.buffer/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.buffer/client.rpt new file mode 100644 index 0000000000..0e51052e64 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.buffer/client.rpt @@ -0,0 +1,207 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + + +connected + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} +write notify RETAIN_STARTED +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(2) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +write notify BUFFERED_MESSAGES_ARRIVED + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message4" + +write notify MESSAGES_FINISHED + +connect await MESSAGES_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read advised zilla:flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.buffer/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.buffer/server.rpt new file mode 100644 index 0000000000..a58a77e6a4 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.buffer/server.rpt @@ -0,0 +1,219 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + + +read await RETAIN_STARTED +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(2) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +read await BUFFERED_MESSAGES_ARRIVED +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message4" +write flush + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write notify RETAIN_STARTED + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +write advise zilla:flush + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.resubscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.resubscribe/client.rpt new file mode 100644 index 0000000000..8b015c3f7f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.resubscribe/client.rpt @@ -0,0 +1,221 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read advised zilla:flush + +write close +read closed + +write notify RETAINED_FINISHED + +connect await RETAINED_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + + +connected + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + +write notify RETAIN_FINISHED + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" +write notify MESSAGES_FINISHED + +connect await MESSAGES_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read advised zilla:flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.resubscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.resubscribe/server.rpt new file mode 100644 index 0000000000..388f259a09 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain.resubscribe/server.rpt @@ -0,0 +1,225 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write advise zilla:flush + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .build() + .build()} + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + +read await RETAIN_FINISHED +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" +write flush + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write advise zilla:flush + +read closed +write close + +write notify RETAIN_FINISHED diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain/client.rpt new file mode 100644 index 0000000000..7a2fbc461f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain/client.rpt @@ -0,0 +1,205 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + + +connected + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + +write notify MESSAGES_FINISHED + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message3" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(2) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message4" + +connect await MESSAGES_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" + +read advised zilla:flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain/server.rpt new file mode 100644 index 0000000000..3eaf1b11dd --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.filter.change.retain/server.rpt @@ -0,0 +1,218 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + + +read await RETAIN_FINISHED +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message3" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(2) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message4" +write flush + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/two") + .header("zilla:filter", "sensor") + .header("zilla:filter", "two") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +write advise zilla:flush + +read closed +write close + +write notify RETAIN_FINISHED diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.multiple.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.multiple.message/client.rpt new file mode 100644 index 0000000000..0dc97a4e64 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.multiple.message/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.multiple.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.multiple.message/server.rpt new file mode 100644 index 0000000000..9c3a5f0ae7 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.multiple.message/server.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.changed.topic.name/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.changed.topic.name/client.rpt new file mode 100644 index 0000000000..c44e724db0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.changed.topic.name/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.changed.topic.name/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.changed.topic.name/server.rpt new file mode 100644 index 0000000000..53cd0c9dfa --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.changed.topic.name/server.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt new file mode 100644 index 0000000000..76fd2f4b7c --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:content-type", "message") + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "sensor/one") + .header("zilla:correlation-id", "info") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt new file mode 100644 index 0000000000..db41db77df --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .headerInt("zilla:timeout-ms", 15000) + .header("zilla:content-type", "message") + .header("zilla:format", "TEXT") + .header("zilla:reply-to", "sensor/one") + .header("zilla:correlation-id", "info") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/client.rpt new file mode 100644 index 0000000000..45b065c2b8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/client.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .header("row1", "1") + .header("row2", "2") + .header("row2", "3") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/server.rpt new file mode 100644 index 0000000000..77147647be --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message.user.properties.unaltered/server.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .header("row1", "1") + .header("row2", "2") + .header("row2", "3") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/client.rpt new file mode 100644 index 0000000000..0dc97a4e64 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/server.rpt new file mode 100644 index 0000000000..d40f6234ba --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.one.message/server.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/client.rpt new file mode 100644 index 0000000000..ad316bf519 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/client.rpt @@ -0,0 +1,86 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .headerNot("zilla:local", "client") + .build() + .evaluation("EAGER") + .build() + .build()} +connected + +write notify FIRST_CONNECTED + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client2") + .header("zilla:format", "TEXT") + .build() + .build()} +read "message2" + + +connect await FIRST_CONNECTED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/server.rpt new file mode 100644 index 0000000000..f9735c5ce2 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.publish.no.local/server.rpt @@ -0,0 +1,89 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .headerNot("zilla:local", "client") + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client2") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("LEADER_ONLY") + .build() + .build()} + + +connected + + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .deferred(0) + .partition(-1, -1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/client.rpt new file mode 100644 index 0000000000..10b353f6de --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/client.rpt @@ -0,0 +1,77 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skipMany() + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .sequence(1) + .build() + .headerNot("zilla:local", "client") + .build() + .build() + .build()} + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(3) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one/1") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:filter", "1") + .header("zilla:local", "client2") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/server.rpt new file mode 100644 index 0000000000..3c399fdc23 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard/server.rpt @@ -0,0 +1,81 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skipMany() + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .sequence(1) + .build() + .headerNot("zilla:local", "client") + .build() + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(3) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one/1") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:filter", "1") + .header("zilla:local", "client2") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/client.rpt new file mode 100644 index 0000000000..d21c2fd61a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .build() + .build() + .evaluation("EAGER") + .build() + .build()} +connected + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" \ No newline at end of file diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/server.rpt new file mode 100644 index 0000000000..e3ecdaf7ab --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.wildcard/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retain/client.rpt new file mode 100644 index 0000000000..10e110e5a1 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retain/client.rpt @@ -0,0 +1,99 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message" + +read advised zilla:flush + +write close +read closed + +write notify RETAINED_FINISHED + +connect await RETAINED_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +read "message2" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retain/server.rpt new file mode 100644 index 0000000000..ab47fb0e89 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retain/server.rpt @@ -0,0 +1,99 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message" +write flush + +write advise zilla:flush + +read closed +write close + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .timestamp(kafka:timestamp()) + .filters(1) + .partition(0, 1, 2) + .progress(0, 2) + .progress(1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:format", "TEXT") + .build() + .build()} + +write "message2" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.abort/client.rpt new file mode 100644 index 0000000000..015cad105a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.abort/client.rpt @@ -0,0 +1,64 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read aborted + +write notify RETAINED_FINISHED + +connect await RETAINED_FINISHED + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read aborted + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.abort/server.rpt new file mode 100644 index 0000000000..0e010982af --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.abort/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write abort + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.reset/client.rpt new file mode 100644 index 0000000000..f39375e961 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.reset/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.reset/server.rpt new file mode 100644 index 0000000000..e87b038279 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.retained.server.sent.reset/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-retained") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/client.rpt new file mode 100644 index 0000000000..b0ed384d92 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/server.rpt new file mode 100644 index 0000000000..3c84065f22 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.abort/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/client.rpt new file mode 100644 index 0000000000..06e86035df --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/server.rpt new file mode 100644 index 0000000000..fa59abf8ee --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.flush/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/client.rpt new file mode 100644 index 0000000000..1072259543 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/server.rpt new file mode 100644 index 0000000000..85495f1536 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.server.sent.reset/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/client.rpt new file mode 100644 index 0000000000..41dd5cfac0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/client.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/server.rpt new file mode 100644 index 0000000000..d8072a6049 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.multi.level.wildcard/server.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt new file mode 100644 index 0000000000..022a6f0e82 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .sequence(1) + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt new file mode 100644 index 0000000000..431e58d345 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .sequence(1) + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected \ No newline at end of file diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/client.rpt new file mode 100644 index 0000000000..bdff98e118 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/client.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .build() + .build() + .evaluation("EAGER") + .build() + .build()} +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/server.rpt new file mode 100644 index 0000000000..5bc23a0493 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.single.level.wildcard/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + + +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/client.rpt new file mode 100644 index 0000000000..524ef4f2b2 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skip(1) + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/server.rpt new file mode 100644 index 0000000000..4ea64808b5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filter.two.single.level.wildcard/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skip(1) + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/client.rpt new file mode 100644 index 0000000000..9df346ca49 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/client.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/server.rpt new file mode 100644 index 0000000000..eca0521ab6 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.both.exact/server.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + + +connected + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt new file mode 100644 index 0000000000..fdb64b861f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("device") + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt new file mode 100644 index 0000000000..ea4e40f667 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("device") + .skipMany() + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/client.rpt new file mode 100644 index 0000000000..11fbfac661 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/server.rpt new file mode 100644 index 0000000000..c3982cc85b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.both.exact/server.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt new file mode 100644 index 0000000000..926bc2d4e2 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("device") + .skipMany() + .build() + .build() + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt new file mode 100644 index 0000000000..48f2130f6b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("device") + .skipMany() + .build() + .build() + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/client.rpt new file mode 100644 index 0000000000..854fbef248 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skipMany() + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .sequence("1") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/server.rpt new file mode 100644 index 0000000000..0b6321c810 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.topic.filters.overlapping.wildcards/server.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .skipMany() + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .skip(1) + .sequence("1") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/client.rpt new file mode 100644 index 0000000000..44cc63a326 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/server.rpt new file mode 100644 index 0000000000..bc72156423 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.after.subscribe/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/client.rpt new file mode 100644 index 0000000000..a52610fe01 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/client.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/server.rpt new file mode 100644 index 0000000000..01b777ce0f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/unsubscribe.topic.filter.single/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("FETCH_ONLY") + .topic("mqtt-messages") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("one") + .build() + .build() + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .evaluation("EAGER") + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .fetch() + .capabilities("FETCH_ONLY") + .filter() + .headers("zilla:filter") + .sequence("sensor") + .sequence("two") + .build() + .build() + .build() + .build()} diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.abort/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.client.sent.reset/server.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/client.rpt new file mode 100644 index 0000000000..3e8a298f5f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/server.rpt new file mode 100644 index 0000000000..4921b6f355 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.empty.message/server.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.clients/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.clients/client.rpt new file mode 100644 index 0000000000..bf7b5195af --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.clients/client.rpt @@ -0,0 +1,104 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client-1") + .topic("sensor/one") + .build() + .build()} + +connected + +write notify RECEIVED_REPLY_BEGIN +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message1" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message3" +write flush + +connect await RECEIVED_REPLY_BEGIN + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client-2") + .topic("sensor/two") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message1" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message3" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.clients/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.clients/server.rpt new file mode 100644 index 0000000000..a49dd2795d --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.clients/server.rpt @@ -0,0 +1,96 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client-1") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message1" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message3" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client-2") + .topic("sensor/two") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message1" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message3" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/client.rpt new file mode 100644 index 0000000000..e53c7280ef --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/client.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message1" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message3" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/server.rpt new file mode 100644 index 0000000000..3d6a18ceef --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.multiple.messages/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message1" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message3" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/client.rpt new file mode 100644 index 0000000000..643c9a0e10 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/client.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +write "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/server.rpt new file mode 100644 index 0000000000..afa02348b8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.one.message/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.abort/client.rpt new file mode 100644 index 0000000000..305f243c8d --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.abort/client.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.abort/server.rpt new file mode 100644 index 0000000000..1ffe3f4ef5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.abort/server.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.data/client.rpt new file mode 100644 index 0000000000..0f0e0f2879 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.data/client.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.data/server.rpt new file mode 100644 index 0000000000..25c52a4dac --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.data/server.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/client.rpt new file mode 100644 index 0000000000..e62fd29994 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/client.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/server.rpt new file mode 100644 index 0000000000..0d654c898a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/server.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.reset/client.rpt new file mode 100644 index 0000000000..734b829363 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.reset/client.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.reset/server.rpt new file mode 100644 index 0000000000..bd93328a97 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.reset/server.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained/client.rpt new file mode 100644 index 0000000000..2efb496b7c --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained/client.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +write "message3" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained/server.rpt new file mode 100644 index 0000000000..42e19c0983 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .format("TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} + +read "message3" diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/client.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/server.rpt new file mode 100644 index 0000000000..279dae2053 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.abort/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/client.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/server.rpt new file mode 100644 index 0000000000..c13d731570 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.data/server.rpt @@ -0,0 +1,33 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/client.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt new file mode 100644 index 0000000000..4fae513f0c --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write advise zilla:flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/client.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/server.rpt new file mode 100644 index 0000000000..6940fdf073 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.reset/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/client.rpt new file mode 100644 index 0000000000..b6c6f8a8ea --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("sensors/1") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .userProperty("row1", "1") + .userProperty("row2", "2") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/server.rpt new file mode 100644 index 0000000000..2d27454157 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.distinct/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("sensors/1") + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .userProperty("row1", "1") + .userProperty("row2", "2") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/client.rpt new file mode 100644 index 0000000000..00078e021e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("sensors/1") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .userProperty("row1", "1") + .userProperty("row1", "2") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/server.rpt new file mode 100644 index 0000000000..8fbf71f2cd --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.properties.repeated/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("sensors/1") + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .userProperty("row1", "1") + .userProperty("row1", "2") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/client.rpt new file mode 100644 index 0000000000..d2837a872e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("sensors/1") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .userProperty("row", "1") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/server.rpt new file mode 100644 index 0000000000..0ec620300b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.with.user.property/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("sensors/1") + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .userProperty("row", "1") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.expire.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.expire.session.state/client.rpt new file mode 100644 index 0000000000..8df5293153 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.expire.session.state/client.rpt @@ -0,0 +1,35 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await SIGNAL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.empty + +write abort +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.expire.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.expire.session.state/server.rpt new file mode 100644 index 0000000000..be7bfea47a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.expire.session.state/server.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.reconnect.non.clean.start/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.reconnect.non.clean.start/client.rpt new file mode 100644 index 0000000000..1d83b99862 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.reconnect.non.clean.start/client.rpt @@ -0,0 +1,116 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION1_READY + +write abort +read aborted +write notify SESSION1_ABORTED + + +connect await SESSION1_READY + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} +connected + +write abort +read aborted + +connect await SESSION1_ABORTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION_READY2 + +connect await SESSION_READY2 + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.reconnect.non.clean.start/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.reconnect.non.clean.start/server.rpt new file mode 100644 index 0000000000..3aa61ab5c0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.abort.reconnect.non.clean.start/server.rpt @@ -0,0 +1,110 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +read aborted +write abort + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read aborted +write abort + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.sent.reset/client.rpt new file mode 100644 index 0000000000..628c0114fe --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.sent.reset/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.sent.reset/server.rpt new file mode 100644 index 0000000000..7afd1331b1 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.sent.reset/server.rpt @@ -0,0 +1,35 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.takeover/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.takeover/client.rpt new file mode 100644 index 0000000000..047113b2db --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.takeover/client.rpt @@ -0,0 +1,114 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify READ_SESSION_STATE + +read closed +write close + +connect await READ_SESSION_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} +connected +write notify CONNECTED + +write close +read closed + + +connect await CONNECTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION_READY2 + +connect await SESSION_READY2 + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.takeover/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.takeover/server.rpt new file mode 100644 index 0000000000..756f369c1c --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.client.takeover/server.rpt @@ -0,0 +1,112 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read await CLIENT_TAKEOVER + +write close +read closed + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read closed +write close + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write notify CLIENT_TAKEOVER + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.close.expire.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.close.expire.session.state/client.rpt new file mode 100644 index 0000000000..0a23695f58 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.close.expire.session.state/client.rpt @@ -0,0 +1,35 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await SIGNAL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.empty + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.close.expire.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.close.expire.session.state/server.rpt new file mode 100644 index 0000000000..58940fdcd8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.close.expire.session.state/server.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.max.session.expiry/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.max.session.expiry/client.rpt new file mode 100644 index 0000000000..9b17e7cb7a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.max.session.expiry/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(100) + .clientId("client-1") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(30) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.max.session.expiry/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.max.session.expiry/server.rpt new file mode 100644 index 0000000000..2232e77d8d --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.max.session.expiry/server.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(100) + .clientId("client-1") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(30) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.min.session.expiry/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.min.session.expiry/client.rpt new file mode 100644 index 0000000000..1b98a74e50 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.min.session.expiry/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(0) + .clientId("client-1") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(2) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.min.session.expiry/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.min.session.expiry/server.rpt new file mode 100644 index 0000000000..4916dcb1ed --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.connect.override.min.session.expiry/server.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(0) + .clientId("client-1") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(2) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.exists.clean.start/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.exists.clean.start/client.rpt new file mode 100644 index 0000000000..6fe5bec3e8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.exists.clean.start/client.rpt @@ -0,0 +1,102 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + +write notify READ_SESSION_EMPTY + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION_READY + +read closed +write close + + +connect await READ_SESSION_EMPTY + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write close +read closed + +connect await SESSION_READY + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +write zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.exists.clean.start/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.exists.clean.start/server.rpt new file mode 100644 index 0000000000..6475a7af1f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.exists.clean.start/server.rpt @@ -0,0 +1,91 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write close +read closed + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read closed +write close + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.redirect/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.redirect/client.rpt new file mode 100644 index 0000000000..c38a0850d0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.redirect/client.rpt @@ -0,0 +1,35 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .serverRef("mqtt-2.example.com:1883") + .build()} + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.redirect/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.redirect/server.rpt new file mode 100644 index 0000000000..7b9e265b8b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.redirect/server.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .serverRef("mqtt-2.example.com:1883") + .build()} + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.server.sent.reset/client.rpt new file mode 100644 index 0000000000..d45c693511 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.server.sent.reset/client.rpt @@ -0,0 +1,32 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.server.sent.reset/server.rpt new file mode 100644 index 0000000000..3a13bf2953 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.server.sent.reset/server.rpt @@ -0,0 +1,35 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe.via.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe.via.session.state/client.rpt new file mode 100644 index 0000000000..64a0c9dfe3 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe.via.session.state/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +connect await SESSION_STATE_SENT + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe.via.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe.via.session.state/server.rpt new file mode 100644 index 0000000000..5a6717a9be --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe.via.session.state/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write notify SESSION_STATE_SENT +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/client.rpt new file mode 100644 index 0000000000..89d347cb45 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/client.rpt @@ -0,0 +1,85 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .qosMax(0) + .packetSizeMax(9216) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + +write notify READ_EMPTY_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + + +connect await READ_EMPTY_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/server.rpt new file mode 100644 index 0000000000..931e03badf --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/server.rpt @@ -0,0 +1,81 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .qosMax(0) + .packetSizeMax(9216) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +write "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.after.subscribe/client.rpt new file mode 100644 index 0000000000..a3e5b43a95 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.after.subscribe/client.rpt @@ -0,0 +1,88 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + +write notify READ_EMPTY_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +write ${mqtt:session() + .build()} + +read ${mqtt:session() + .build()} + + + +connect await READ_EMPTY_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.after.subscribe/server.rpt new file mode 100644 index 0000000000..a5a01e3656 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.after.subscribe/server.rpt @@ -0,0 +1,87 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +read ${mqtt:session() + .build()} + +write ${mqtt:session() + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +write "message" + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.via.session.state/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.via.session.state/client.rpt new file mode 100644 index 0000000000..12f50776ef --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.via.session.state/client.rpt @@ -0,0 +1,69 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify READ_SESSION_STATE + +read ${mqtt:session() + .build()} + + +connect await READ_SESSION_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.via.session.state/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.via.session.state/server.rpt new file mode 100644 index 0000000000..cf6802be63 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.unsubscribe.via.session.state/server.rpt @@ -0,0 +1,69 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read await READ_SESSION_STATE +write ${mqtt:session() + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-1") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will.retain/client.rpt new file mode 100644 index 0000000000..668d5303aa --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will.retain/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await WILL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("obituaries") + .delay(1) + .flags("RETAIN") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read zilla:data.empty + +write abort +read aborted + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will.retain/server.rpt new file mode 100644 index 0000000000..a9513c2214 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will.retain/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1) + .flags("RETAIN") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} + +write zilla:data.empty +write flush + +read aborted +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will/client.rpt new file mode 100644 index 0000000000..8c8e901c5e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will/client.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await WILL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("obituaries") + .delay(1) + .expiryInterval(15) + .format("TEXT") + .responseTopic("responses/client1") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read zilla:data.empty + +write abort +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will/server.rpt new file mode 100644 index 0000000000..d2b66cf1c7 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.abort.deliver.will/server.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1) + .expiryInterval(15) + .format("TEXT") + .responseTopic("responses/client1") + .correlation("info") + .payload("client-1 disconnected abruptly") + .build()} + +write zilla:data.empty +write flush + +read aborted +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.clean.start/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.clean.start/client.rpt new file mode 100644 index 0000000000..09ad926815 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.clean.start/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await WILL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read zilla:data.empty + +write zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.clean.start/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.clean.start/server.rpt new file mode 100644 index 0000000000..f8ab41ce05 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.clean.start/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} + +write zilla:data.empty +write flush + +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.normal.disconnect/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.normal.disconnect/client.rpt new file mode 100644 index 0000000000..490bc13a57 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.normal.disconnect/client.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await WILL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} +write flush + + +#We only expect this, after the will-signal and will message was saved to Kafka +read zilla:data.empty + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.normal.disconnect/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.normal.disconnect/server.rpt new file mode 100644 index 0000000000..c2fae0e893 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.normal.disconnect/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} + +write zilla:data.empty +write flush + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.reconnect.non.clean.start/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.reconnect.non.clean.start/client.rpt new file mode 100644 index 0000000000..f58852f608 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.reconnect.non.clean.start/client.rpt @@ -0,0 +1,79 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} +write flush + +read zilla:data.empty +read notify RECEIVED_CONNACK_TRIGGER + +read closed +write close + +connect await RECEIVED_CONNACK_TRIGGER + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} +write ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disappeared abruptly") + .build()} +write flush + +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.reconnect.non.clean.start/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.reconnect.non.clean.start/server.rpt new file mode 100644 index 0000000000..f26b19e7d5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.reconnect.non.clean.start/server.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("one") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} + +write zilla:data.empty +write flush + +write close +read closed + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("one") + .build() + .build()} +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} +read ${mqtt:will() + .topic("obituaries") + .format("TEXT") + .payload("client-1 disappeared abruptly") + .build()} + +write zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.takeover.deliver.will/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.takeover.deliver.will/client.rpt new file mode 100644 index 0000000000..ce3007b13a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.takeover.deliver.will/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await WILL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("obituaries") + .delay(1) + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} +write flush + + +#We only expect this, after the will-signal and will message was saved to Kafka +read zilla:data.empty + +read closed +write close diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.takeover.deliver.will/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.takeover.deliver.will/server.rpt new file mode 100644 index 0000000000..ed9cae3310 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message.takeover.deliver.will/server.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1) + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} + +write zilla:data.empty +write flush + +write close +read closed diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message/client.rpt new file mode 100644 index 0000000000..88290a7fc1 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect await WILL_STREAM_STARTED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("obituaries") + .delay(1) + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} +write flush + + +#We only expect this, after the will-signal and will message was saved to Kafka +read zilla:data.empty diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message/server.rpt new file mode 100644 index 0000000000..4f102e37ef --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.will.message/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL") + .expiry(1) + .clientId("client-1") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("obituaries") + .delay(1) + .format("TEXT") + .payload("client-1 disconnected abruptly") + .build()} + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/client.rpt new file mode 100644 index 0000000000..4ebd9d47b4 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/client.rpt @@ -0,0 +1,30 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/server.rpt new file mode 100644 index 0000000000..d87d2aac1f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.abort/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/client.rpt new file mode 100644 index 0000000000..e4845f0b19 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/client.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write zilla:data.empty +write abort \ No newline at end of file diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/server.rpt new file mode 100644 index 0000000000..036048878e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.data/server.rpt @@ -0,0 +1,33 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read zilla:data.empty +read aborted \ No newline at end of file diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/client.rpt new file mode 100644 index 0000000000..ec964b8a62 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/client.rpt @@ -0,0 +1,30 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/server.rpt new file mode 100644 index 0000000000..0877af4fe0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.client.sent.reset/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.deferred.filter.change.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.deferred.filter.change.retain/client.rpt new file mode 100644 index 0000000000..d80d42f600 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.deferred.filter.change.retain/client.rpt @@ -0,0 +1,116 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message2" + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message" + +read await FIRST_RETAINED_SENT +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .filter("sensor/three", 3, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} +write notify SECOND_FLUSH_SENT + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/three") + .subscriptionId(3) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message3" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.deferred.filter.change.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.deferred.filter.change.retain/server.rpt new file mode 100644 index 0000000000..3c9d2bc5f6 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.deferred.filter.change.retain/server.rpt @@ -0,0 +1,124 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write notify FIRST_RETAINED_SENT + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .filter("sensor/three", 3, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/three") + .subscriptionId(3) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message3" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain.resubscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain.resubscribe/client.rpt new file mode 100644 index 0000000000..5fca4ecb70 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain.resubscribe/client.rpt @@ -0,0 +1,100 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message2" + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message3" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain.resubscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain.resubscribe/server.rpt new file mode 100644 index 0000000000..f0ef61f05c --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain.resubscribe/server.rpt @@ -0,0 +1,108 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message3" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain/client.rpt new file mode 100644 index 0000000000..d8a5fd2bee --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain/client.rpt @@ -0,0 +1,117 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message2" + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message3" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message2" + +write notify BUFFERED_MESSAGES_ARRIVED + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message4" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain/server.rpt new file mode 100644 index 0000000000..3480ca9925 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.filter.change.retain/server.rpt @@ -0,0 +1,125 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1, "AT_MOST_ONCE") + .filter("sensor/two", 2, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .flags("RETAIN") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message3" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message4" + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.multiple.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.multiple.message/client.rpt new file mode 100644 index 0000000000..f9f1557cc6 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.multiple.message/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message2" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.multiple.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.multiple.message/server.rpt new file mode 100644 index 0000000000..809d879c90 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.multiple.message/server.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message.user.properties.unaltered/server.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/client.rpt new file mode 100644 index 0000000000..9fdc50a839 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/server.rpt new file mode 100644 index 0000000000..809d879c90 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.one.message/server.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/client.rpt new file mode 100644 index 0000000000..2cc96bc157 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/client.rpt @@ -0,0 +1,65 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build() + .build()} + +connected + +write notify SUBSCRIBED + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message2" + + +connect await SUBSCRIBED + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +write "message" +write flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/server.rpt new file mode 100644 index 0000000000..a39048ad56 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.publish.no.local/server.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +write "message2" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/client.rpt new file mode 100644 index 0000000000..d52dffc7e9 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/#", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/+/#", 1) + .filter("sensor/+/1", 2, "AT_MOST_ONCE", "NO_LOCAL") + .build() + .build()} + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one/1") + .subscriptionId(1) + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/server.rpt new file mode 100644 index 0000000000..c686a815c8 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.overlapping.wildcard/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/#", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/+/#", 1) + .filter("sensor/+/1", 2, "AT_MOST_ONCE", "NO_LOCAL") + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one/1") + .subscriptionId(1) + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.receive.message.wildcard/server.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain.as.published/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain.as.published/client.rpt new file mode 100644 index 0000000000..a7816a5a76 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain.as.published/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .flags("RETAIN") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message2" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain.as.published/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain.as.published/server.rpt new file mode 100644 index 0000000000..723f81abaa --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain.as.published/server.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .flags("RETAIN") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain/client.rpt new file mode 100644 index 0000000000..0d766258ca --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain/client.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message2" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain/server.rpt new file mode 100644 index 0000000000..e3541ceb78 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retain/server.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message2" +write flush + diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.abort/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.abort/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.abort/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.abort/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.flush/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.flush/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.flush/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.flush/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.reset/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.reset/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.reset/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.retained.server.sent.reset/server.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/client.rpt new file mode 100644 index 0000000000..3bea6e1ab7 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/client.rpt @@ -0,0 +1,30 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/server.rpt new file mode 100644 index 0000000000..fcc9e8f07c --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.abort/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/client.rpt new file mode 100644 index 0000000000..0b10daa322 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/client.rpt @@ -0,0 +1,30 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/server.rpt new file mode 100644 index 0000000000..1bfa319425 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.flush/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/client.rpt new file mode 100644 index 0000000000..85187364fb --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/client.rpt @@ -0,0 +1,30 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +write aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/server.rpt new file mode 100644 index 0000000000..773cbf8ff5 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.server.sent.reset/server.rpt @@ -0,0 +1,31 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read abort diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.multi.level.wildcard/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.single.level.wildcard/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filter.two.single.level.wildcard/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.both.exact/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.both.exact/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/subscribe.topic.filters.overlapping.wildcards/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.after.subscribe/server.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/client.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/client.rpt diff --git a/incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/server.rpt similarity index 100% rename from incubator/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/unsubscribe.topic.filter.single/server.rpt diff --git a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/config/SchemaTest.java b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/config/SchemaTest.java new file mode 100644 index 0000000000..f70d2087fb --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/config/SchemaTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.kafka.config; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; + +import jakarta.json.JsonObject; + +import org.junit.Rule; +import org.junit.Test; + +import io.aklivity.zilla.specs.engine.config.ConfigSchemaRule; + +public class SchemaTest +{ + @Rule + public final ConfigSchemaRule schema = new ConfigSchemaRule() + .schemaPatch("io/aklivity/zilla/specs/binding/mqtt/kafka/schema/mqtt.kafka.schema.patch.json") + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config"); + + + @Test + public void shouldValidateProxy() + { + JsonObject config = schema.validate("proxy.yaml"); + + assertThat(config, not(nullValue())); + } + + @Test + public void shouldValidateProxyWithOptions() + { + JsonObject config = schema.validate("proxy.options.yaml"); + + assertThat(config, not(nullValue())); + } +} diff --git a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java new file mode 100644 index 0000000000..b683ff1426 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java @@ -0,0 +1,721 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.kafka.streams; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class KafkaIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("kafka", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${kafka}/publish.client.sent.abort/client", + "${kafka}/publish.client.sent.abort/server"}) + public void shouldPublishReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.client.sent.reset/client", + "${kafka}/publish.client.sent.reset/server"}) + public void shouldPublishReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.server.sent.abort/client", + "${kafka}/publish.server.sent.abort/server"}) + public void shouldPublishReceiveServerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.server.sent.flush/client", + "${kafka}/publish.server.sent.flush/server"}) + public void shouldPublishReceiveServerSentFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.server.sent.reset/client", + "${kafka}/publish.server.sent.reset/server"}) + public void shouldPublishReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.server.sent.data/client", + "${kafka}/publish.server.sent.data/server"}) + public void shouldPublishAbortWhenServerSentData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.retained.server.sent.abort/client", + "${kafka}/publish.retained.server.sent.abort/server"}) + public void shouldPublishReceiveServerSentRetainedAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.retained.server.sent.flush/client", + "${kafka}/publish.retained.server.sent.flush/server"}) + public void shouldPublishReceiveServerSentRetainedFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.retained.server.sent.reset/client", + "${kafka}/publish.retained.server.sent.reset/server"}) + public void shouldPublishReceiveServerSentRetainedReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.retained.server.sent.data/client", + "${kafka}/publish.retained.server.sent.data/server"}) + public void shouldPublishAbortWhenServerSentRetainedData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.empty.message/client", + "${kafka}/publish.empty.message/server"}) + public void shouldSendEmptyMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.one.message/client", + "${kafka}/publish.one.message/server"}) + public void shouldSendOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.one.message.changed.topic.name/client", + "${kafka}/publish.one.message.changed.topic.name/server"}) + public void shouldSendOneMessageWithChangedTopicName() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.retained/client", + "${kafka}/publish.retained/server"}) + public void shouldPublishRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.multiple.messages/client", + "${kafka}/publish.multiple.messages/server"}) + public void shouldSendMultipleMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.multiple.clients/client", + "${kafka}/publish.multiple.clients/server"}) + public void shouldSendMultipleClients() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.with.user.properties.distinct/client", + "${kafka}/publish.with.user.properties.distinct/server"}) + public void shouldSendWithDistinctUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.with.user.properties.repeated/client", + "${kafka}/publish.with.user.properties.repeated/server"}) + public void shouldSendWithRepeatedUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.with.user.property/client", + "${kafka}/publish.with.user.property/server"}) + public void shouldSendWithUserProperty() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.client.sent.abort/client", + "${kafka}/subscribe.client.sent.abort/server"}) + public void shouldSubscribeReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.client.sent.data/client", + "${kafka}/subscribe.client.sent.data/server"}) + public void shouldSubscribeAbortWhenClientSentData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.client.sent.reset/client", + "${kafka}/subscribe.client.sent.reset/server"}) + public void shouldSubscribeReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.server.sent.abort/client", + "${kafka}/subscribe.server.sent.abort/server"}) + public void shouldSubscribeReceiveServerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.server.sent.flush/client", + "${kafka}/subscribe.server.sent.flush/server"}) + public void shouldSubscribeReceiveServerSentFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.server.sent.reset/client", + "${kafka}/subscribe.server.sent.reset/server"}) + public void shouldSubscribeReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.retained.server.sent.abort/client", + "${kafka}/subscribe.retained.server.sent.abort/server"}) + public void shouldSubscribeReceiveServerSentRetainedAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.retained.server.sent.reset/client", + "${kafka}/subscribe.retained.server.sent.reset/server"}) + public void shouldSubscribeReceiveServerSentRetainedReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.filter.change.retain/client", + "${kafka}/subscribe.filter.change.retain/server"}) + public void shouldReceiveRetainedAfterFilterChange() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.deferred.filter.change.retain/client", + "${kafka}/subscribe.deferred.filter.change.retain/server"}) + public void shouldReceiveRetainedAfterFilterDeferred() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.filter.change.retain.buffer/client", + "${kafka}/subscribe.filter.change.retain.buffer/server"}) + public void shouldReceiveRetainedAfterFilterChangeBuffer() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.filter.change.retain.resubscribe/client", + "${kafka}/subscribe.filter.change.retain.resubscribe/server"}) + public void shouldReceiveRetainedAfterFilterChangeResubscribe() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.one.message/client", + "${kafka}/subscribe.one.message/server"}) + public void shouldReceiveOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.one.message.changed.topic.name/client", + "${kafka}/subscribe.one.message.changed.topic.name/server"}) + public void shouldReceiveOneMessageWithChangedTopicName() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.one.message.receive.response.topic.and.correlation.data/client", + "${kafka}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) + public void shouldReceiveCorrelationData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.one.message.user.properties.unaltered/client", + "${kafka}/subscribe.one.message.user.properties.unaltered/server"}) + public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.publish.no.local/client", + "${kafka}/subscribe.publish.no.local/server"}) + public void shouldNotReceiveLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.retain/client", + "${kafka}/subscribe.retain/server"}) + public void shouldReceiveRetained() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.receive.message.wildcard/client", + "${kafka}/subscribe.receive.message.wildcard/server"}) + public void shouldReceiveOneMessageWithPatternTopic() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.receive.message.overlapping.wildcard/client", + "${kafka}/subscribe.receive.message.overlapping.wildcard/server"}) + public void shouldReceiveMessageOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filter.multi.level.wildcard/client", + "${kafka}/subscribe.topic.filter.multi.level.wildcard/server"}) + public void shouldFilterMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filter.single.level.wildcard/client", + "${kafka}/subscribe.topic.filter.single.level.wildcard/server"}) + public void shouldFilterSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filter.single.and.multi.level.wildcard/client", + "${kafka}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) + public void shouldFilterSingleAndMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filter.two.single.level.wildcard/client", + "${kafka}/subscribe.topic.filter.two.single.level.wildcard/server"}) + public void shouldFilterTwoSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filters.aggregated.both.exact/client", + "${kafka}/subscribe.topic.filters.aggregated.both.exact/server"}) + public void shouldFilterAggregatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filters.isolated.both.exact/client", + "${kafka}/subscribe.topic.filters.isolated.both.exact/server"}) + public void shouldFilterIsolatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filters.overlapping.wildcards/client", + "${kafka}/subscribe.topic.filters.overlapping.wildcards/server"}) + public void shouldFilterOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", + "${kafka}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) + public void shouldFilterAggregatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/subscribe.topic.filters.isolated.exact.and.wildcard/client", + "${kafka}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) + public void shouldFilterIsolatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/unsubscribe.after.subscribe/client", + "${kafka}/unsubscribe.after.subscribe/server"}) + public void shouldAcknowledge() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/unsubscribe.topic.filter.single/client", + "${kafka}/unsubscribe.topic.filter.single/server"}) + public void shouldAcknowledgeSingleTopicFilter() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.abort.reconnect.non.clean.start/client", + "${kafka}/session.abort.reconnect.non.clean.start/server"}) + public void shouldReconnectNonCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.client.takeover/client", + "${kafka}/session.client.takeover/server"}) + public void shouldTakeOverSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.exists.clean.start/client", + "${kafka}/session.exists.clean.start/server"}) + public void shouldRemoveSessionAtCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.subscribe/client", + "${kafka}/session.subscribe/server"}) + public void shouldSubscribeSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.subscribe.via.session.state/client", + "${kafka}/session.subscribe.via.session.state/server"}) + public void shouldReceiveMessageSubscribedViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.unsubscribe.after.subscribe/client", + "${kafka}/session.unsubscribe.after.subscribe/server"}) + public void shouldUnsubscribeAndUpdateSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.unsubscribe.via.session.state/client", + "${kafka}/session.unsubscribe.via.session.state/server"}) + public void shouldUnsubscribeViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.client.sent.reset/client", + "${kafka}/session.client.sent.reset/server"}) + public void shouldSessionStreamReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.server.sent.reset/client", + "${kafka}/session.server.sent.reset/server"}) + public void shouldSessionStreamReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.group.server.sent.reset/client", + "${kafka}/session.group.server.sent.reset/server"}) + public void shouldGroupStreamReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.close.expire.session.state/client", + "${kafka}/session.close.expire.session.state/server"}) + public void shouldExpireSessionOnClose() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.abort.expire.session.state/client", + "${kafka}/session.abort.expire.session.state/server"}) + public void shouldExpireSessionOnAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.cancel.session.expiry/client", + "${kafka}/session.cancel.session.expiry/server"}) + public void shouldCancelSessionExpiry() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.message.abort.deliver.will/client", + "${kafka}/session.will.message.abort.deliver.will/server"}) + public void shouldSendWillMessageOnAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.message.normal.disconnect/client", + "${kafka}/session.will.message.normal.disconnect/server"}) + public void shouldNotSendWillMessageOnNormalDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.message.abort.deliver.will.retain/client", + "${kafka}/session.will.message.abort.deliver.will.retain/server"}) + public void shouldSaveWillMessageAsRetain() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.message.clean.start/client", + "${kafka}/session.will.message.clean.start/server"}) + public void shouldGenerateLifeTimeIdOnCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.message.will.id.mismatch.skip.delivery/client", + "${kafka}/session.will.message.will.id.mismatch.skip.delivery/server"}) + public void shouldNotSendWillMessageOnWillIdMismatch() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.message.takeover.deliver.will/client", + "${kafka}/session.will.message.takeover.deliver.will/server"}) + public void shouldSendWillMessageOnSessionTakeover() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.message.cancel.delivery/client", + "${kafka}/session.will.message.cancel.delivery/server"}) + public void shouldCancelWillDelivery() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.stream.end.reconnect/client", + "${kafka}/session.will.stream.end.reconnect/server"}) + public void shouldReconnectWillStreamOnKafkaEnd() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.stream.abort.reconnect/client", + "${kafka}/session.will.stream.abort.reconnect/server"}) + public void shouldReconnectWillStreamOnKafkaAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.will.stream.reset.reconnect/client", + "${kafka}/session.will.stream.reset.reconnect/server"}) + public void shouldReconnectWillStreamOnKafkaReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.connect.override.max.session.expiry/client", + "${kafka}/session.connect.override.max.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiryTooBig() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.connect.override.min.session.expiry/client", + "${kafka}/session.connect.override.min.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiryTooSmall() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/session.redirect/client", + "${kafka}/session.redirect/server"}) + public void shouldRedirect() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java new file mode 100644 index 0000000000..cbd728c02b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java @@ -0,0 +1,602 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.kafka.streams; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class MqttIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("mqtt", "io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${mqtt}/publish.client.sent.abort/client", + "${mqtt}/publish.client.sent.abort/server"}) + public void shouldReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.client.sent.reset/client", + "${mqtt}/publish.client.sent.reset/server"}) + public void shouldReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.server.sent.abort/client", + "${mqtt}/publish.server.sent.abort/server"}) + public void shouldPublishReceiveServerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.server.sent.flush/client", + "${mqtt}/publish.server.sent.flush/server"}) + public void shouldPublishReceiveServerSentFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.server.sent.reset/client", + "${mqtt}/publish.server.sent.reset/server"}) + public void shouldPublishReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.server.sent.data/client", + "${mqtt}/publish.server.sent.data/server"}) + public void shouldPublishAbortWhenServerSentData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.empty.message/client", + "${mqtt}/publish.empty.message/server"}) + public void shouldSendEmptyMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.one.message/client", + "${mqtt}/publish.one.message/server"}) + public void shouldSendOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.multiple.messages/client", + "${mqtt}/publish.multiple.messages/server"}) + public void shouldSendMultipleMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.multiple.clients/client", + "${mqtt}/publish.multiple.clients/server"}) + public void shouldSendMultipleClients() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.retained/client", + "${mqtt}/publish.retained/server"}) + public void shouldPublishRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.with.user.properties.distinct/client", + "${mqtt}/publish.with.user.properties.distinct/server"}) + public void shouldSendWithDistinctUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.with.user.properties.repeated/client", + "${mqtt}/publish.with.user.properties.repeated/server"}) + public void shouldSendWithRepeatedUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.with.user.property/client", + "${mqtt}/publish.with.user.property/server"}) + public void shouldSendWithUserProperty() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.client.sent.abort/client", + "${mqtt}/subscribe.client.sent.abort/server"}) + public void shouldSubscribeReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.client.sent.data/client", + "${mqtt}/subscribe.client.sent.data/server"}) + public void shouldSubscribeAbortWhenClientSentData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.client.sent.reset/client", + "${mqtt}/subscribe.client.sent.reset/server"}) + public void shouldSubscribeReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.server.sent.abort/client", + "${mqtt}/subscribe.server.sent.abort/server"}) + public void shouldSubscribeReceiveServerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.server.sent.flush/client", + "${mqtt}/subscribe.server.sent.flush/server"}) + public void shouldSubscribeReceiveServerSentFlush() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.server.sent.reset/client", + "${mqtt}/subscribe.server.sent.reset/server"}) + public void shouldSubscribeReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.one.message/client", + "${mqtt}/subscribe.one.message/server"}) + public void shouldReceiveOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.one.message.receive.response.topic.and.correlation.data/client", + "${mqtt}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) + public void shouldReceiveCorrelationData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.retain/client", + "${mqtt}/subscribe.retain/server"}) + public void shouldReceiveRetainedNoRetainAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.retain.as.published/client", + "${mqtt}/subscribe.retain.as.published/server"}) + public void shouldReceiveRetainAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.filter.change.retain/client", + "${mqtt}/subscribe.filter.change.retain/server"}) + public void shouldReceiveRetainedAfterFilterChange() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.deferred.filter.change.retain/client", + "${mqtt}/subscribe.deferred.filter.change.retain/server"}) + public void shouldReceiveRetainedAfterFilterChangeDeferred() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.filter.change.retain.resubscribe/client", + "${mqtt}/subscribe.filter.change.retain.resubscribe/server"}) + public void shouldReceiveRetainedAfterFilterChangeResubscribe() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.publish.no.local/client", + "${mqtt}/subscribe.publish.no.local/server"}) + public void shouldNotReceiveLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.receive.message.overlapping.wildcard/client", + "${mqtt}/subscribe.receive.message.overlapping.wildcard/server"}) + public void shouldReceiveMessageOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.receive.message.wildcard/client", + "${mqtt}/subscribe.receive.message.wildcard/server"}) + public void shouldReceiveOneMessageWithPatternTopic() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filter.multi.level.wildcard/client", + "${mqtt}/subscribe.topic.filter.multi.level.wildcard/server"}) + public void shouldFilterMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filter.single.level.wildcard/client", + "${mqtt}/subscribe.topic.filter.single.level.wildcard/server"}) + public void shouldFilterSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filter.single.and.multi.level.wildcard/client", + "${mqtt}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) + public void shouldFilterSingleAndMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.one.message.user.properties.unaltered/client", + "${mqtt}/subscribe.one.message.user.properties.unaltered/server"}) + public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filter.two.single.level.wildcard/client", + "${mqtt}/subscribe.topic.filter.two.single.level.wildcard/server"}) + public void shouldFilterTwoSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filters.aggregated.both.exact/client", + "${mqtt}/subscribe.topic.filters.aggregated.both.exact/server"}) + public void shouldFilterAggregatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filters.isolated.both.exact/client", + "${mqtt}/subscribe.topic.filters.isolated.both.exact/server"}) + public void shouldFilterIsolatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filters.overlapping.wildcards/client", + "${mqtt}/subscribe.topic.filters.overlapping.wildcards/server"}) + public void shouldFilterOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", + "${mqtt}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) + public void shouldFilterAggregatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/subscribe.topic.filters.isolated.exact.and.wildcard/client", + "${mqtt}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) + public void shouldFilterIsolatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/unsubscribe.after.subscribe/client", + "${mqtt}/unsubscribe.after.subscribe/server"}) + public void shouldAcknowledge() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/unsubscribe.topic.filter.single/client", + "${mqtt}/unsubscribe.topic.filter.single/server"}) + public void shouldAcknowledgeSingleTopicFilter() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.connect.override.max.session.expiry/client", + "${mqtt}/session.connect.override.max.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiryTooBig() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.connect.override.min.session.expiry/client", + "${mqtt}/session.connect.override.min.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiryTooSmall() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.abort.reconnect.non.clean.start/client", + "${mqtt}/session.abort.reconnect.non.clean.start/server"}) + public void shouldReconnectNonCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.client.takeover/client", + "${mqtt}/session.client.takeover/server"}) + public void shouldTakeOverSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.exists.clean.start/client", + "${mqtt}/session.exists.clean.start/server"}) + public void shouldRemoveSessionAtCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.subscribe/client", + "${mqtt}/session.subscribe/server"}) + public void shouldSubscribeSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.subscribe.via.session.state/client", + "${mqtt}/session.subscribe.via.session.state/server"}) + public void shouldReceiveMessageSubscribedViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.unsubscribe.after.subscribe/client", + "${mqtt}/session.unsubscribe.after.subscribe/server"}) + public void shouldUnsubscribeAndUpdateSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.unsubscribe.via.session.state/client", + "${mqtt}/session.unsubscribe.via.session.state/server"}) + public void shouldUnsubscribeViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.client.sent.reset/client", + "${mqtt}/session.client.sent.reset/server"}) + public void shouldSessionStreamReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.server.sent.reset/client", + "${mqtt}/session.server.sent.reset/server"}) + public void shouldSessionStreamReceiveServerSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.close.expire.session.state/client", + "${mqtt}/session.close.expire.session.state/server"}) + public void shouldExpireSessionOnClose() throws Exception + { + k3po.start(); + k3po.notifyBarrier("SIGNAL_STREAM_STARTED"); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.abort.expire.session.state/client", + "${mqtt}/session.abort.expire.session.state/server"}) + public void shouldExpireSessionOnAbort() throws Exception + { + k3po.start(); + k3po.notifyBarrier("SIGNAL_STREAM_STARTED"); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.will.message.abort.deliver.will/client", + "${mqtt}/session.will.message.abort.deliver.will/server"}) + public void shouldSendWillMessageOnAbort() throws Exception + { + k3po.start(); + k3po.notifyBarrier("WILL_STREAM_STARTED"); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.will.message.normal.disconnect/client", + "${mqtt}/session.will.message.normal.disconnect/server"}) + public void shouldNotSendWillMessageOnNormalDisconnect() throws Exception + { + k3po.start(); + k3po.notifyBarrier("WILL_STREAM_STARTED"); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.will.message.abort.deliver.will.retain/client", + "${mqtt}/session.will.message.abort.deliver.will.retain/server"}) + public void shouldSaveWillMessageAsRetain() throws Exception + { + k3po.start(); + k3po.notifyBarrier("WILL_STREAM_STARTED"); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.will.message.clean.start/client", + "${mqtt}/session.will.message.clean.start/server"}) + public void shouldSendWillMessageOnClientReconnectCleanStart() throws Exception + { + k3po.start(); + k3po.notifyBarrier("WILL_STREAM_STARTED"); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.will.message.takeover.deliver.will/client", + "${mqtt}/session.will.message.takeover.deliver.will/server"}) + public void shouldDeliverWillMessageOnSessionTakeover() throws Exception + { + k3po.start(); + k3po.notifyBarrier("WILL_STREAM_STARTED"); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/session.will.message/client", + "${mqtt}/session.will.message/server"}) + public void shouldSaveWillMessage() throws Exception + { + k3po.start(); + k3po.notifyBarrier("WILL_STREAM_STARTED"); + k3po.finish(); + } +} diff --git a/incubator/binding-mqtt/COPYRIGHT b/specs/binding-mqtt.spec/COPYRIGHT similarity index 100% rename from incubator/binding-mqtt/COPYRIGHT rename to specs/binding-mqtt.spec/COPYRIGHT diff --git a/incubator/binding-mqtt/LICENSE b/specs/binding-mqtt.spec/LICENSE similarity index 100% rename from incubator/binding-mqtt/LICENSE rename to specs/binding-mqtt.spec/LICENSE diff --git a/incubator/binding-mqtt.spec/NOTICE b/specs/binding-mqtt.spec/NOTICE similarity index 100% rename from incubator/binding-mqtt.spec/NOTICE rename to specs/binding-mqtt.spec/NOTICE diff --git a/incubator/binding-mqtt/NOTICE.template b/specs/binding-mqtt.spec/NOTICE.template similarity index 100% rename from incubator/binding-mqtt/NOTICE.template rename to specs/binding-mqtt.spec/NOTICE.template diff --git a/specs/binding-mqtt.spec/mvnw b/specs/binding-mqtt.spec/mvnw new file mode 100755 index 0000000000..d2f0ea3808 --- /dev/null +++ b/specs/binding-mqtt.spec/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + 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" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/specs/binding-mqtt.spec/mvnw.cmd b/specs/binding-mqtt.spec/mvnw.cmd new file mode 100644 index 0000000000..b26ab24f03 --- /dev/null +++ b/specs/binding-mqtt.spec/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/specs/binding-mqtt.spec/pom.xml b/specs/binding-mqtt.spec/pom.xml new file mode 100644 index 0000000000..66a8f87601 --- /dev/null +++ b/specs/binding-mqtt.spec/pom.xml @@ -0,0 +1,161 @@ + + + + 4.0.0 + + io.aklivity.zilla + specs + 0.9.52 + ../pom.xml + + + binding-mqtt.spec + zilla::specs::binding-mqtt.spec + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + 11 + 11 + 0.94 + 0 + + + + + org.kaazing + k3po.lang + provided + + + ${project.groupId} + engine.spec + ${project.version} + + + junit + junit + test + + + org.kaazing + k3po.junit + test + + + org.hamcrest + hamcrest-library + test + + + + + + + src/main/resources + + + src/main/scripts + + + + + + org.jasig.maven + maven-notice-plugin + + + ${project.groupId} + flyweight-maven-plugin + ${project.version} + + core mqtt + io.aklivity.zilla.specs.binding.mqtt.internal.types + + + + + validate + generate + + + + + + com.mycila + license-maven-plugin + + + maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.moditect + moditect-maven-plugin + + + org.kaazing + k3po-maven-plugin + + + ${project.groupId} + engine + ${project.version} + test-jar + + + ${project.groupId} + engine + ${project.version} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.jacoco + jacoco-maven-plugin + + + io/aklivity/zilla/specs/binding/mqtt/internal/types/**/*.class + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + ${jacoco.coverage.ratio} + + + CLASS + MISSEDCOUNT + ${jacoco.missed.count} + + + + + + + + + diff --git a/incubator/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java b/specs/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java similarity index 76% rename from incubator/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java rename to specs/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java index 58807ebe47..8653be2e7f 100644 --- a/incubator/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java +++ b/specs/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java @@ -15,10 +15,12 @@ */ package io.aklivity.zilla.specs.binding.mqtt.internal; +import static java.lang.System.currentTimeMillis; import static java.nio.charset.StandardCharsets.UTF_8; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.concurrent.ThreadLocalRandom; import java.util.function.Predicate; import org.agrona.DirectBuffer; @@ -30,26 +32,33 @@ import io.aklivity.zilla.specs.binding.mqtt.internal.types.Array32FW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttBinaryFW; -import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttEndReasonCode; -import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttMessageFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttExpirySignalFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttPayloadFormat; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttPayloadFormatFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttPublishFlags; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttQoS; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSessionFlags; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSessionSignalFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSessionSignalType; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSessionStateFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSubscribeFlags; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttTopicFilterFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttUserPropertyFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttWillMessageFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttWillSignalFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.String16FW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.Varuint32FW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttDataExFW; -import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttEndExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttExtensionKind; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttFlushExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttPublishBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttPublishDataExFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttResetExFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttServerCapabilities; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSessionBeginExFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSessionDataExFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSessionDataKind; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSubscribeBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSubscribeDataExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSubscribeFlushExFW; @@ -99,9 +108,9 @@ public static MqttFlushExBuilder flushEx() } @Function - public static MqttEndExBuilder endEx() + public static MqttResetExBuilder resetEx() { - return new MqttEndExBuilder(); + return new MqttResetExBuilder(); } @Function @@ -110,6 +119,36 @@ public static MqttSessionStateBuilder session() return new MqttSessionStateBuilder(); } + @Function + public static MqttWillMessageBuilder will() + { + return new MqttWillMessageBuilder(); + } + + @Function + public static MqttSessionSignalBuilder sessionSignal() + { + return new MqttSessionSignalBuilder(); + } + + @Function + public static long timestamp() + { + return currentTimeMillis(); + } + + @Function + public static byte[] randomBytes( + int length) + { + byte[] bytes = new byte[length]; + for (int i = 0; i < length; i++) + { + bytes[i] = (byte) ThreadLocalRandom.current().nextInt(0x100); + } + return bytes; + } + public static final class MqttBeginExBuilder { private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); @@ -183,22 +222,45 @@ public MqttSessionBeginExBuilder expiry( return this; } - public MqttWillMessageBuilder will() + public MqttSessionBeginExBuilder qosMax( + int qosMax) { - return new MqttWillMessageBuilder(this); + sessionBeginExRW.qosMax(qosMax); + return this; } - public MqttBeginExBuilder build() + public MqttSessionBeginExBuilder packetSizeMax( + int packetSizeMax) { - final MqttSessionBeginExFW subscribeBeginEx = sessionBeginExRW.build(); - beginExRO.wrap(writeBuffer, 0, subscribeBeginEx.limit()); - return MqttBeginExBuilder.this; + sessionBeginExRW.packetSizeMax(packetSizeMax); + return this; } - private void willMessage( - MqttMessageFW willMessage) + public MqttSessionBeginExBuilder capabilities( + String... capabilityNames) { - sessionBeginExRW.will(willMessage); + int capabilities = Arrays.stream(capabilityNames) + .mapToInt(flag -> 1 << MqttServerCapabilities.valueOf(flag).value()) + .reduce(0, (a, b) -> a | b); + sessionBeginExRW.capabilities(capabilities); + return this; + } + + public MqttSessionBeginExBuilder flags( + String... flagNames) + { + int flags = Arrays.stream(flagNames) + .mapToInt(flag -> 1 << MqttSessionFlags.valueOf(flag).value()) + .reduce(0, (a, b) -> a | b); + sessionBeginExRW.flags(flags); + return this; + } + + public MqttBeginExBuilder build() + { + final MqttSessionBeginExFW sessionBeginEx = sessionBeginExRW.build(); + beginExRO.wrap(writeBuffer, 0, sessionBeginEx.limit()); + return MqttBeginExBuilder.this; } } @@ -278,6 +340,16 @@ public MqttPublishBeginExBuilder topic( return this; } + public MqttPublishBeginExBuilder flags( + String... flagNames) + { + int flags = Arrays.stream(flagNames) + .mapToInt(flag -> 1 << MqttPublishFlags.valueOf(flag).ordinal()) + .reduce(0, (a, b) -> a | b); + publishBeginExRW.flags(flags); + return this; + } + public MqttBeginExBuilder build() { final MqttPublishBeginExFW publishBeginEx = publishBeginExRW.build(); @@ -321,6 +393,13 @@ public MqttDataExBuilder.MqttPublishDataExBuilder publish() return new MqttDataExBuilder.MqttPublishDataExBuilder(); } + public MqttDataExBuilder.MqttSessionDataExBuilder session() + { + dataExRW.kind(MqttExtensionKind.SESSION.value()); + + return new MqttDataExBuilder.MqttSessionDataExBuilder(); + } + public byte[] build() { final MqttDataExFW dataEx = dataExRO; @@ -437,13 +516,6 @@ private MqttPublishDataExBuilder() publishDataExRW.wrap(writeBuffer, MqttBeginExFW.FIELD_OFFSET_PUBLISH, writeBuffer.capacity()); } - public MqttPublishDataExBuilder topic( - String topic) - { - publishDataExRW.topic(topic); - return this; - } - public MqttPublishDataExBuilder qos( String qos) { @@ -513,8 +585,32 @@ public MqttPublishDataExBuilder userProperty( public MqttDataExBuilder build() { - final MqttPublishDataExFW publishBeginEx = publishDataExRW.build(); - dataExRO.wrap(writeBuffer, 0, publishBeginEx.limit()); + final MqttPublishDataExFW publishDataEx = publishDataExRW.build(); + dataExRO.wrap(writeBuffer, 0, publishDataEx.limit()); + return MqttDataExBuilder.this; + } + } + + public final class MqttSessionDataExBuilder + { + private final MqttSessionDataExFW.Builder sessionDataExRW = new MqttSessionDataExFW.Builder(); + + private MqttSessionDataExBuilder() + { + sessionDataExRW.wrap(writeBuffer, MqttBeginExFW.FIELD_OFFSET_SESSION, writeBuffer.capacity()); + } + + public MqttSessionDataExBuilder kind( + String kind) + { + sessionDataExRW.kind(k -> k.set(MqttSessionDataKind.valueOf(kind))); + return this; + } + + public MqttDataExBuilder build() + { + final MqttSessionDataExFW sessionDataEx = sessionDataExRW.build(); + dataExRO.wrap(writeBuffer, 0, sessionDataEx.limit()); return MqttDataExBuilder.this; } } @@ -595,35 +691,42 @@ public byte[] build() } } - public static final class MqttEndExBuilder + public static final class MqttResetExBuilder { - private final MqttEndExFW.Builder endExRW; + private final MqttResetExFW.Builder resetExRW; - private MqttEndExBuilder() + private MqttResetExBuilder() { MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); - this.endExRW = new MqttEndExFW.Builder().wrap(writeBuffer, 0, writeBuffer.capacity()); + this.resetExRW = new MqttResetExFW.Builder().wrap(writeBuffer, 0, writeBuffer.capacity()); } - public MqttEndExBuilder typeId( + public MqttResetExBuilder typeId( int typeId) { - endExRW.typeId(typeId); + resetExRW.typeId(typeId); + return this; + } + + public MqttResetExBuilder serverRef( + String serverRef) + { + resetExRW.serverRef(serverRef); return this; } - public MqttEndExBuilder reason( - String reason) + public MqttResetExBuilder reasonCode( + int reasonCode) { - endExRW.reasonCode(r -> r.set(MqttEndReasonCode.valueOf(reason))); + resetExRW.reasonCode(reasonCode); return this; } public byte[] build() { - final MqttEndExFW endEx = endExRW.build(); - final byte[] array = new byte[endEx.sizeof()]; - endEx.buffer().getBytes(endEx.offset(), array); + final MqttResetExFW resetEx = resetExRW.build(); + final byte[] array = new byte[resetEx.sizeof()]; + resetEx.buffer().getBytes(resetEx.offset(), array); return array; } } @@ -638,13 +741,6 @@ private MqttSessionStateBuilder() sessionStateRW.wrap(writeBuffer, 0, writeBuffer.capacity()); } - public MqttSessionStateBuilder clientId( - String clientId) - { - sessionStateRW.clientId(clientId); - return this; - } - public MqttSessionStateBuilder subscription( String pattern) { @@ -660,6 +756,15 @@ public MqttSessionStateBuilder subscription( return this; } + public MqttSessionStateBuilder subscription( + String pattern, + int id, + int reasonCode) + { + sessionStateRW.subscriptionsItem(f -> f.subscriptionId(id).reasonCode(reasonCode).pattern(pattern)); + return this; + } + public MqttSessionStateBuilder subscription( String pattern, int id, @@ -685,12 +790,11 @@ public byte[] build() public static final class MqttWillMessageBuilder { - private final MqttMessageFW.Builder willMessageRW = new MqttMessageFW.Builder(); - private final MqttBeginExBuilder.MqttSessionBeginExBuilder beginExBuilder; + private final MqttWillMessageFW.Builder willMessageRW = new MqttWillMessageFW.Builder(); + private final MqttWillMessageFW willMessageRO = new MqttWillMessageFW(); - private MqttWillMessageBuilder(MqttBeginExBuilder.MqttSessionBeginExBuilder beginExBuilder) + private MqttWillMessageBuilder() { - this.beginExBuilder = beginExBuilder; MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); willMessageRW.wrap(writeBuffer, 0, writeBuffer.capacity()); } @@ -754,6 +858,20 @@ public MqttWillMessageBuilder responseTopic( return this; } + public MqttWillMessageBuilder lifetimeId( + String lifetimeId) + { + willMessageRW.lifetimeId(lifetimeId); + return this; + } + + public MqttWillMessageBuilder willId( + String willId) + { + willMessageRW.willId(willId); + return this; + } + public MqttWillMessageBuilder correlation( String correlation) { @@ -790,13 +908,158 @@ public MqttWillMessageBuilder payloadBytes( return this; } - public MqttBeginExBuilder.MqttSessionBeginExBuilder build() + public byte[] build() + { + final MqttWillMessageFW willMessage = willMessageRW.build(); + final byte[] array = new byte[willMessage.sizeof()]; + willMessage.buffer().getBytes(willMessage.offset(), array); + return array; + } + } + + public static final class MqttSessionSignalBuilder + { + private final MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + + private final MqttSessionSignalFW signalRO = new MqttSessionSignalFW(); + + private final MqttSessionSignalFW.Builder signalRW = new MqttSessionSignalFW.Builder(); + + + private MqttSessionSignalBuilder() + { + signalRW.wrap(writeBuffer, 0, writeBuffer.capacity()); + } + + public MqttSessionExpirySignalBuilder expiry() + { + signalRW.kind(MqttSessionSignalType.EXPIRY.value()); + + return new MqttSessionExpirySignalBuilder(); + } + + public MqttSessionWillSignalBuilder will() { - beginExBuilder.willMessage(willMessageRW.build()); - return beginExBuilder; + signalRW.kind(MqttSessionSignalType.WILL.value()); + + return new MqttSessionWillSignalBuilder(); + } + + public byte[] build() + { + final MqttSessionSignalFW signal = signalRO; + final byte[] array = new byte[signal.sizeof()]; + signal.buffer().getBytes(signal.offset(), array); + return array; + } + + + public final class MqttSessionWillSignalBuilder + { + private final MqttWillSignalFW.Builder willSignalRW = new MqttWillSignalFW.Builder(); + + private MqttSessionWillSignalBuilder() + { + willSignalRW.wrap(writeBuffer, MqttSessionSignalFW.FIELD_OFFSET_WILL, writeBuffer.capacity()); + } + + public MqttSessionWillSignalBuilder clientId( + String clientId) + { + willSignalRW.clientId(clientId); + return this; + } + + public MqttSessionWillSignalBuilder delay( + int delay) + { + willSignalRW.delay(delay); + return this; + } + + public MqttSessionWillSignalBuilder deliverAt( + long deliverAt) + { + willSignalRW.deliverAt(deliverAt); + return this; + } + + public MqttSessionWillSignalBuilder lifetimeId( + String lifetimeId) + { + willSignalRW.lifetimeId(lifetimeId); + return this; + } + + public MqttSessionWillSignalBuilder willId( + String willId) + { + willSignalRW.willId(willId); + return this; + } + + public MqttSessionWillSignalBuilder instanceId( + String instanceId) + { + willSignalRW.instanceId(instanceId); + return this; + } + + public MqttSessionSignalBuilder build() + { + final MqttWillSignalFW willSignal = willSignalRW.build(); + signalRO.wrap(writeBuffer, 0, willSignal.limit()); + return MqttSessionSignalBuilder.this; + } + } + + public final class MqttSessionExpirySignalBuilder + { + private final MqttExpirySignalFW.Builder expirySignalRW = new MqttExpirySignalFW.Builder(); + + private MqttSessionExpirySignalBuilder() + { + expirySignalRW.wrap(writeBuffer, MqttSessionSignalFW.FIELD_OFFSET_EXPIRY, writeBuffer.capacity()); + } + + public MqttSessionExpirySignalBuilder clientId( + String clientId) + { + expirySignalRW.clientId(clientId); + return this; + } + + public MqttSessionExpirySignalBuilder delay( + int delay) + { + expirySignalRW.delay(delay); + return this; + } + + public MqttSessionExpirySignalBuilder expireAt( + long expireAt) + { + expirySignalRW.expireAt(expireAt); + return this; + } + + public MqttSessionExpirySignalBuilder instanceId( + String instanceId) + { + expirySignalRW.instanceId(instanceId); + return this; + } + + public MqttSessionSignalBuilder build() + { + final MqttExpirySignalFW expirySignal = expirySignalRW.build(); + signalRO.wrap(writeBuffer, 0, expirySignal.limit()); + return MqttSessionSignalBuilder.this; + } } } + public static final class MqttBeginExMatcherBuilder { private final DirectBuffer bufferRO = new UnsafeBuffer(); @@ -807,6 +1070,15 @@ public static final class MqttBeginExMatcherBuilder private Integer kind; private Predicate caseMatcher; + public MqttPublishBeginExMatcherBuilder publish() + { + final MqttPublishBeginExMatcherBuilder matcherBuilder = new MqttPublishBeginExMatcherBuilder(); + + this.kind = MqttExtensionKind.PUBLISH.value(); + this.caseMatcher = matcherBuilder::match; + return matcherBuilder; + } + public MqttSubscribeBeginExMatcherBuilder subscribe() { final MqttSubscribeBeginExMatcherBuilder matcherBuilder = new MqttSubscribeBeginExMatcherBuilder(); @@ -878,6 +1150,73 @@ private boolean matchCase( return caseMatcher == null || caseMatcher.test(beginEx); } + public final class MqttPublishBeginExMatcherBuilder + { + private String16FW clientId; + private String16FW topic; + private Integer flags; + + private MqttPublishBeginExMatcherBuilder() + { + } + public MqttPublishBeginExMatcherBuilder clientId( + String clientId) + { + this.clientId = new String16FW(clientId); + return this; + } + + public MqttPublishBeginExMatcherBuilder topic( + String topic) + { + this.topic = new String16FW(topic); + return this; + } + + public MqttPublishBeginExMatcherBuilder flags( + String... flags) + { + this.flags = Arrays.stream(flags) + .mapToInt(flag -> 1 << MqttPublishFlags.valueOf(flag).ordinal()) + .reduce(0, (a, b) -> a | b); + return this; + } + + + public MqttBeginExMatcherBuilder build() + { + return MqttBeginExMatcherBuilder.this; + } + + private boolean match( + MqttBeginExFW beginEx) + { + final MqttPublishBeginExFW publishBeginEx = beginEx.publish(); + return matchClientId(publishBeginEx) && + matchTopic(publishBeginEx) && + matchFlags(publishBeginEx); + } + + private boolean matchClientId( + final MqttPublishBeginExFW publishBeginEx) + { + return clientId == null || clientId.equals(publishBeginEx.clientId()); + } + + + private boolean matchTopic( + final MqttPublishBeginExFW publishBeginEx) + { + return topic == null || topic.equals(publishBeginEx.topic()); + } + + private boolean matchFlags( + final MqttPublishBeginExFW publishBeginEx) + { + return flags == null || flags == publishBeginEx.flags(); + } + } + public final class MqttSubscribeBeginExMatcherBuilder { private String16FW clientId; @@ -974,9 +1313,11 @@ private boolean matchFilters( public final class MqttSessionBeginExMatcherBuilder { private String16FW clientId; - private Integer expiry; - private MqttWillMessageMatcherBuilder willMessageMatcher; + private Integer flags; + private Integer capabilities; + private Integer qosMax; + private Integer packetSizeMax; private MqttSessionBeginExMatcherBuilder() { @@ -996,10 +1337,36 @@ public MqttSessionBeginExMatcherBuilder expiry( return this; } - public MqttWillMessageMatcherBuilder will() + public MqttSessionBeginExMatcherBuilder qosMax( + int qosMax) + { + this.qosMax = qosMax; + return this; + } + + public MqttSessionBeginExMatcherBuilder capabilities( + String... capabilityNames) { - this.willMessageMatcher = new MqttWillMessageMatcherBuilder(); - return willMessageMatcher; + this.capabilities = Arrays.stream(capabilityNames) + .mapToInt(flag -> 1 << MqttServerCapabilities.valueOf(flag).value()) + .reduce(0, (a, b) -> a | b); + return this; + } + + public MqttSessionBeginExMatcherBuilder packetSizeMax( + int packetSizeMax) + { + this.packetSizeMax = packetSizeMax; + return this; + } + + public MqttSessionBeginExMatcherBuilder flags( + String... flagNames) + { + this.flags = Arrays.stream(flagNames) + .mapToInt(flag -> 1 << MqttSessionFlags.valueOf(flag).value()) + .reduce(0, (a, b) -> a | b); + return this; } public MqttBeginExMatcherBuilder build() @@ -1011,10 +1378,12 @@ private boolean match( MqttBeginExFW beginEx) { final MqttSessionBeginExFW sessionBeginEx = beginEx.session(); - final MqttMessageFW willMessage = beginEx.session().will(); - return matchClientId(sessionBeginEx) && + return matchFlags(sessionBeginEx) && + matchClientId(sessionBeginEx) && matchExpiry(sessionBeginEx) && - (willMessageMatcher == null || willMessageMatcher.match(willMessage)); + matchQosMax(sessionBeginEx) && + matchPacketSizeMax(sessionBeginEx) && + matchCapabilities(sessionBeginEx); } private boolean matchClientId( @@ -1023,241 +1392,34 @@ private boolean matchClientId( return clientId == null || clientId.equals(sessionBeginEx.clientId()); } - private boolean matchExpiry( + private boolean matchQosMax( final MqttSessionBeginExFW sessionBeginEx) { - return expiry == null || expiry == sessionBeginEx.expiry(); + return qosMax == null || qosMax == sessionBeginEx.qosMax(); } - public final class MqttWillMessageMatcherBuilder + private boolean matchPacketSizeMax( + final MqttSessionBeginExFW sessionBeginEx) { - private MqttBinaryFW.Builder correlationRW; - private final DirectBuffer correlationRO = new UnsafeBuffer(0, 0); - private MqttBinaryFW.Builder payloadRW; - private final DirectBuffer payloadRO = new UnsafeBuffer(0, 0); - private String16FW topic; - private Integer delay; - private Integer qos; - private Integer flags; - private Integer expiryInterval = -1; - private String16FW contentType; - private MqttPayloadFormatFW format; - private String16FW responseTopic; - private Array32FW.Builder userPropertiesRW; - - private MqttWillMessageMatcherBuilder() - { - } - - public MqttWillMessageMatcherBuilder topic( - String topic) - { - this.topic = new String16FW(topic); - return this; - } - - public MqttWillMessageMatcherBuilder delay( - int delay) - { - this.delay = delay; - return this; - } - - public MqttWillMessageMatcherBuilder qos( - String qos) - { - this.qos = MqttQoS.valueOf(qos).ordinal(); - return this; - } - - public MqttWillMessageMatcherBuilder flags( - String... flagNames) - { - int flags = Arrays.stream(flagNames) - .mapToInt(flag -> 1 << MqttPublishFlags.valueOf(flag).ordinal()) - .reduce(0, (a, b) -> a | b); - this.flags = flags; - return this; - } - - public MqttWillMessageMatcherBuilder expiryInterval( - int expiryInterval) - { - this.expiryInterval = expiryInterval; - return this; - } - - public MqttWillMessageMatcherBuilder contentType( - String contentType) - { - this.contentType = new String16FW(contentType); - return this; - } - - public MqttWillMessageMatcherBuilder format( - String format) - { - MqttPayloadFormatFW.Builder builder = - new MqttPayloadFormatFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); - this.format = builder.set(MqttPayloadFormat.valueOf(format)).build(); - return this; - } - - public MqttWillMessageMatcherBuilder responseTopic( - String topic) - { - this.responseTopic = new String16FW(topic); - return this; - } - - public MqttWillMessageMatcherBuilder correlation( - String correlation) - { - assert correlationRW == null; - correlationRW = new MqttBinaryFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); - - correlationRO.wrap(correlation.getBytes(UTF_8)); - correlationRW.bytes(correlationRO, 0, correlationRO.capacity()); - - return this; - } - - public MqttWillMessageMatcherBuilder correlationBytes( - byte[] correlation) - { - assert correlationRW == null; - correlationRW = new MqttBinaryFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); - - correlationRO.wrap(correlation); - correlationRW.bytes(correlationRO, 0, correlationRO.capacity()); - - return this; - } - - public MqttWillMessageMatcherBuilder userProperty( - String name, - String value) - { - if (userPropertiesRW == null) - { - this.userPropertiesRW = - new Array32FW.Builder<>(new MqttUserPropertyFW.Builder(), new MqttUserPropertyFW()) - .wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); - } - userPropertiesRW.item(p -> p.key(name).value(value)); - return this; - } - - public MqttWillMessageMatcherBuilder payload( - String payload) - { - assert payloadRW == null; - payloadRW = new MqttBinaryFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); - - payloadRO.wrap(payload.getBytes(UTF_8)); - payloadRW.bytes(payloadRO, 0, payloadRO.capacity()); - - return this; - } - - public MqttWillMessageMatcherBuilder payloadBytes( - byte[] payload) - { - assert payloadRW == null; - payloadRW = new MqttBinaryFW.Builder().wrap(new UnsafeBuffer(new byte[1024]), 0, 1024); - - payloadRO.wrap(payload); - payloadRW.bytes(payloadRO, 0, payloadRO.capacity()); - - return this; - } - - public MqttSessionBeginExMatcherBuilder build() - { - return MqttSessionBeginExMatcherBuilder.this; - } - - private boolean match( - MqttMessageFW willMessage) - { - return matchTopic(willMessage) && - matchDelay(willMessage) && - matchQos(willMessage) && - matchFlags(willMessage) && - matchExpiryInterval(willMessage) && - matchContentType(willMessage) && - matchFormat(willMessage) && - matchResponseTopic(willMessage) && - matchCorrelation(willMessage) && - matchUserProperties(willMessage) && - matchPayload(willMessage); - } - - private boolean matchTopic( - final MqttMessageFW willMessage) - { - return topic == null || topic.equals(willMessage.topic()); - } - - private boolean matchDelay( - final MqttMessageFW willMessage) - { - return delay == null || delay == willMessage.delay(); - } - - private boolean matchQos( - final MqttMessageFW willMessage) - { - return qos == null || qos == willMessage.qos(); - } - - private boolean matchFlags( - final MqttMessageFW willMessage) - { - return flags == null || flags == willMessage.flags(); - } - - private boolean matchExpiryInterval( - final MqttMessageFW willMessage) - { - return expiryInterval == null || expiryInterval == willMessage.expiryInterval(); - } - - private boolean matchContentType( - final MqttMessageFW willMessage) - { - return contentType == null || contentType.equals(willMessage.contentType()); - } - - private boolean matchFormat( - final MqttMessageFW willMessage) - { - return format == null || format.equals(willMessage.format()); - } - - private boolean matchResponseTopic( - final MqttMessageFW willMessage) - { - return responseTopic == null || responseTopic.equals(willMessage.responseTopic()); - } + return packetSizeMax == null || packetSizeMax == sessionBeginEx.packetSizeMax(); + } - private boolean matchCorrelation( - final MqttMessageFW willMessage) - { - return correlationRW == null || correlationRW.build().equals(willMessage.correlation()); - } + private boolean matchCapabilities( + final MqttSessionBeginExFW sessionBeginEx) + { + return capabilities == null || capabilities == sessionBeginEx.capabilities(); + } - private boolean matchUserProperties( - final MqttMessageFW willMessage) - { - return userPropertiesRW == null || userPropertiesRW.build().equals(willMessage.properties()); - } + private boolean matchExpiry( + final MqttSessionBeginExFW sessionBeginEx) + { + return expiry == null || expiry == sessionBeginEx.expiry(); + } - private boolean matchPayload( - final MqttMessageFW willMessage) - { - return payloadRW == null || payloadRW.build().equals(willMessage.payload()); - } + private boolean matchFlags( + final MqttSessionBeginExFW sessionBeginEx) + { + return flags == null || flags == sessionBeginEx.flags(); } } } @@ -1553,7 +1715,6 @@ public final class MqttPublishDataExMatcherBuilder { private MqttBinaryFW.Builder correlationRW; private final DirectBuffer correlationRO = new UnsafeBuffer(0, 0); - private String16FW topic; private Integer qos; private Integer flags; private Integer expiryInterval = -1; @@ -1566,13 +1727,6 @@ private MqttPublishDataExMatcherBuilder() { } - public MqttPublishDataExMatcherBuilder topic( - String topic) - { - this.topic = new String16FW(topic); - return this; - } - public MqttPublishDataExMatcherBuilder qos( String qos) { @@ -1666,8 +1820,7 @@ private boolean match( MqttDataExFW dataEx) { final MqttPublishDataExFW publishDataEx = dataEx.publish(); - return matchTopic(publishDataEx) && - matchQos(publishDataEx) && + return matchQos(publishDataEx) && matchFlags(publishDataEx) && matchExpiryInterval(publishDataEx) && matchContentType(publishDataEx) && @@ -1677,12 +1830,6 @@ private boolean match( matchUserProperties(publishDataEx); } - private boolean matchTopic( - final MqttPublishDataExFW data) - { - return topic == null || topic.equals(data.topic()); - } - private boolean matchQos( final MqttPublishDataExFW data) { diff --git a/incubator/binding-mqtt.spec/src/main/moditect/module-info.java b/specs/binding-mqtt.spec/src/main/moditect/module-info.java similarity index 100% rename from incubator/binding-mqtt.spec/src/main/moditect/module-info.java rename to specs/binding-mqtt.spec/src/main/moditect/module-info.java diff --git a/incubator/binding-mqtt.spec/src/main/resources/META-INF/services/org.kaazing.k3po.lang.el.spi.FunctionMapperSpi b/specs/binding-mqtt.spec/src/main/resources/META-INF/services/org.kaazing.k3po.lang.el.spi.FunctionMapperSpi similarity index 100% rename from incubator/binding-mqtt.spec/src/main/resources/META-INF/services/org.kaazing.k3po.lang.el.spi.FunctionMapperSpi rename to specs/binding-mqtt.spec/src/main/resources/META-INF/services/org.kaazing.k3po.lang.el.spi.FunctionMapperSpi diff --git a/specs/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl b/specs/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl new file mode 100644 index 0000000000..dc8bb68ca1 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl @@ -0,0 +1,239 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +scope mqtt +{ + enum MqttSessionFlags (uint8) + { + CLEAN_START(1), + WILL(2) + } + + enum MqttSubscribeFlags (uint8) + { + SEND_RETAINED(0), + RETAIN_AS_PUBLISHED(1), + NO_LOCAL(2), + RETAIN(3) + } + + enum MqttQoS (uint8) + { + AT_MOST_ONCE(0), + AT_LEAST_ONCE(1), + EXACTLY_ONCE(2) + } + + enum MqttPublishFlags (uint8) + { + RETAIN(0) + } + + enum MqttPayloadFormat + { + BINARY, + TEXT, + NONE + } + + enum MqttTime (int64) + { + UNKNOWN(-1L) + } + + struct MqttBinary + { + int32 length; + octets[length] bytes = null; + } + + struct MqttUserProperty + { + string16 key; + string16 value; + } + + struct MqttTopicFilter + { + uint32 subscriptionId = 0; + uint8 qos = 0; + uint8 flags = 0; + uint8 reasonCode = 0; + string16 pattern; + } + + struct MqttSessionState + { + uint8 version = 1; + MqttTopicFilter[] subscriptions; + } + + enum MqttSessionSignalType (uint8) + { + WILL (0), + EXPIRY (1) + } + + union MqttSessionSignal switch (uint8) + { + case 0: mqtt::MqttWillSignal will; + case 1: mqtt::MqttExpirySignal expiry; + } + + struct MqttWillSignal + { + string16 instanceId; + string16 clientId; + int32 delay = 0; + int64 deliverAt = -1; + string16 lifetimeId = null; + string16 willId = null; + } + + struct MqttExpirySignal + { + string16 instanceId; + string16 clientId; + int32 delay = 0; + int64 expireAt = -1; + } + + struct MqttWillMessage + { + string16 topic = null; + int32 delay = 0; + uint8 qos = 0; + uint8 flags = 0; + int32 expiryInterval = -1; + string16 contentType = null; + MqttPayloadFormat format = NONE; + string16 responseTopic = null; + string16 lifetimeId = null; + string16 willId = null; + MqttBinary correlation; + MqttUserProperty[] properties; + MqttBinary payload; + } + + scope stream + { + enum MqttExtensionKind (uint8) + { + SESSION (2), + SUBSCRIBE (1), + PUBLISH (0) + } + + union MqttBeginEx switch (uint8) extends core::stream::Extension + { + case 0: mqtt::stream::MqttPublishBeginEx publish; + case 1: mqtt::stream::MqttSubscribeBeginEx subscribe; + case 2: mqtt::stream::MqttSessionBeginEx session; + } + + enum MqttServerCapabilities (uint8) + { + RETAIN (0), + WILDCARD (1), + SUBSCRIPTION_IDS (2), + SHARED_SUBSCRIPTIONS (3) + } + + struct MqttSessionBeginEx + { + uint8 flags = 0; + int32 expiry = 0; + uint16 qosMax = 0; + uint32 packetSizeMax = 0; + uint8 capabilities = 0; + string16 clientId; + } + + struct MqttSubscribeBeginEx + { + string16 clientId; + MqttTopicFilter[] filters; + } + + struct MqttPublishBeginEx + { + string16 clientId; + string16 topic; + uint8 flags = 0; + } + + union MqttDataEx switch (uint8) extends core::stream::Extension + { + case 0: mqtt::stream::MqttPublishDataEx publish; + case 1: mqtt::stream::MqttSubscribeDataEx subscribe; + case 2: mqtt::stream::MqttSessionDataEx session; + } + + struct MqttSubscribeDataEx + { + int32 deferred = 0; // INIT only (TODO: move to DATA frame) + string16 topic = null; + uint8 qos = 0; + uint8 flags = 0; + varuint32[] subscriptionIds; + int32 expiryInterval = -1; + string16 contentType = null; + MqttPayloadFormat format = NONE; + string16 responseTopic = null; + MqttBinary correlation; + MqttUserProperty[] properties; + } + + struct MqttPublishDataEx + { + int32 deferred = 0; // INIT only (TODO: move to DATA frame) + uint8 qos = 0; + uint8 flags = 0; + int32 expiryInterval = -1; + string16 contentType = null; + MqttPayloadFormat format = NONE; + string16 responseTopic = null; + MqttBinary correlation; + MqttUserProperty[] properties; + } + + enum MqttSessionDataKind + { + STATE, + WILL + } + + struct MqttSessionDataEx + { + MqttSessionDataKind kind; + } + + struct MqttResetEx extends core::stream::Extension + { + string16 serverRef = null; + uint8 reasonCode = 0; + } + + union MqttFlushEx switch (uint8) extends core::stream::Extension + { + case 1: mqtt::stream::MqttSubscribeFlushEx subscribe; + } + + struct MqttSubscribeFlushEx + { + MqttTopicFilter[] filters; + } + } +} diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.or.sessions.yaml b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.or.sessions.yaml similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.or.sessions.yaml rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.or.sessions.yaml diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.yaml b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.yaml similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.yaml rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.when.topic.yaml diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.yaml b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.yaml similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.yaml rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/client.yaml diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.credentials.password.yaml b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.credentials.password.yaml new file mode 100644 index 0000000000..cd582c7254 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.credentials.password.yaml @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +--- +name: test +guards: + test0: + type: test + options: + credentials: TOKEN + lifetime: PT5S + challenge: PT5S +bindings: + net0: + type: mqtt + kind: server + options: + authorization: + test0: + credentials: + connect: + password: Bearer {credentials} + routes: + - exit: app0 + guarded: + test0: [] diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.credentials.username.yaml b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.credentials.username.yaml new file mode 100644 index 0000000000..dcc3bf8b4b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.credentials.username.yaml @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +--- +name: test +guards: + test0: + type: test + options: + credentials: TOKEN + lifetime: PT5S + challenge: PT5S +bindings: + net0: + type: mqtt + kind: server + options: + authorization: + test0: + credentials: + connect: + username: Bearer {credentials} + routes: + - exit: app0 + guarded: + test0: [] diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.route.non.default.yaml b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.route.non.default.yaml new file mode 100644 index 0000000000..38e16f2c5c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.route.non.default.yaml @@ -0,0 +1,33 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +--- +name: test +bindings: + net0: + type: mqtt + kind: server + routes: + - when: + - session: + - client-id: "*" + - publish: + - topic: command/one + - topic: command/two + - subscribe: + - topic: reply + exit: app1 + exit: app0 diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.yaml b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.yaml similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.yaml rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/config/server.yaml diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json new file mode 100644 index 0000000000..54d4e16853 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json @@ -0,0 +1,193 @@ +[ + { + "op": "add", + "path": "/$defs/binding/properties/type/enum/-", + "value": "mqtt" + }, + { + "op": "add", + "path": "/$defs/binding/allOf/-", + "value": + { + "if": + { + "properties": + { + "type": + { + "const": "mqtt" + } + } + }, + "then": + { + "properties": + { + "type": + { + "const": "mqtt" + }, + "kind": + { + "enum": [ "server", "client" ] + }, + "vault": false, + "options": + { + "properties": + { + "authorization": + { + "title": "Authorizations", + "type": "object", + "patternProperties": + { + "^[a-zA-Z]+[a-zA-Z0-9\\._\\-]*$": + { + "title": "Guard", + "type": "object", + "properties": + { + "credentials": + { + "title": "Credentials", + "type": "object", + "properties": + { + "connect": + { + "title": "Connect", + "type": "object", + "properties": + { + "username": + { + "title": "Username", + "type": "string" + }, + "password": + { + "title": "Password", + "type": "string" + } + }, + "oneOf": + [ + { + "required": + [ + "username" + ] + }, + { + "required": + [ + "password" + ] + } + ] + } + }, + "additionalProperties": false, + "anyOf": + [ + { + "required": + [ + "connect" + ] + } + ] + } + }, + "additionalProperties": false, + "required": + [ + "credentials" + ] + } + }, + "maxProperties": 1 + } + }, + "additionalProperties": false + }, + "routes": + { + "items": + { + "properties": + { + "when": + { + "items": + { + "additionalProperties": false, + "properties": + { + "session": + { + "title": "Session", + "type": "array", + "items": + { + "client-id": + { + "title": "Client Id", + "type": "string" + } + } + }, + "subscribe": + { + "title": "Subscribe", + "type": "array", + "items": + { + "topic": + { + "title": "Topic", + "type": "string" + } + } + }, + "publish": + { + "title": "Subscribe", + "type": "array", + "items": + { + "topic": + { + "title": "Topic", + "type": "string" + } + } + } + } + } + }, + "with": false + } + } + } + }, + "anyOf": + [ + { + "required": + [ + "exit" + ] + }, + { + "required": + [ + "routes" + ] + } + ] + } + } + } +] diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt new file mode 100644 index 0000000000..b771dafd37 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt new file mode 100644 index 0000000000..b5555172b2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/client.rpt new file mode 100644 index 0000000000..88889bceaa --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(0) + .qosMax(0) + .packetSizeMax(50) + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/server.rpt new file mode 100644 index 0000000000..12aed590e7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(0) + .qosMax(0) + .packetSizeMax(50) + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt new file mode 100644 index 0000000000..923890e1d3 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt @@ -0,0 +1,97 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(50) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .build() + .build()} + +read "message that should not arrive to client, since it exceeds max packet limit" + + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt new file mode 100644 index 0000000000..a8697a4866 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt @@ -0,0 +1,97 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(50) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .build() + .build()} + +write "message that should not arrive to client, since it exceeds max packet limit" +write flush + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/client.rpt new file mode 100644 index 0000000000..c8ed292659 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(0) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/server.rpt new file mode 100644 index 0000000000..7492f9ab3e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(0) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.connack/client.rpt new file mode 100644 index 0000000000..eaf7efbcfa --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.connack/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +connected + +read zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .reasonCode(132) + .build()} + +write aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.connack/server.rpt new file mode 100644 index 0000000000..6e4e8824ed --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.connack/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +connected + +write zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .reasonCode(132) + .build()} +write flush + +read abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/client.rpt new file mode 100644 index 0000000000..365e9bb357 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/client.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + +read zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .reasonCode(129) + .build()} + +write aborted +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/server.rpt new file mode 100644 index 0000000000..e3b9ad7f5f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty + +write zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .reasonCode(129) + .build()} +write flush + +read abort +write close \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/client.rpt new file mode 100644 index 0000000000..4902ad1d9b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/client.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START", "WILL") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write close +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/server.rpt new file mode 100644 index 0000000000..bac2170456 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START", "WILL") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/client.rpt new file mode 100644 index 0000000000..dc21bb3d5d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/server.rpt new file mode 100644 index 0000000000..f94abcde9e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/client.rpt new file mode 100644 index 0000000000..c8b839d1fe --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/client.rpt @@ -0,0 +1,115 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write await RECEIVED_SUBSCRIBE_STREAM_OPEN +write await SENT_PUBLISH_DATA +write close +read closed +read notify RECEIVE_SUBSCRIBE_CLOSED + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected +read notify RECEIVED_SUBSCRIBE_STREAM_OPEN + +write await RECEIVE_SUBSCRIBE_CLOSED +write close +read closed + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message" +write flush +write notify SENT_PUBLISH_DATA + +write close +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/server.rpt new file mode 100644 index 0000000000..367dc5d60f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/server.rpt @@ -0,0 +1,103 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read closed +write close + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message" + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt new file mode 100644 index 0000000000..9aff694e50 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt new file mode 100644 index 0000000000..bda65ca1bd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt @@ -0,0 +1,64 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt new file mode 100644 index 0000000000..f72e494334 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt @@ -0,0 +1,69 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .build() + .build()} +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt new file mode 100644 index 0000000000..c4e8bd3cbf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt new file mode 100644 index 0000000000..bd3c03ccb5 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt new file mode 100644 index 0000000000..1985238c24 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt @@ -0,0 +1,66 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt new file mode 100644 index 0000000000..78c686fb6e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt @@ -0,0 +1,106 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message1" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message3" + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message2" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message4" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt new file mode 100644 index 0000000000..5a00d9a593 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt @@ -0,0 +1,103 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message1" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message3" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .build() + .build()} + +read "message4" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt new file mode 100644 index 0000000000..17b4d208ce --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt @@ -0,0 +1,95 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message1" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message2" + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client2") + .build() + .build()} + +connected + +read zilla:data.empty + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt new file mode 100644 index 0000000000..af8fb2059f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt @@ -0,0 +1,102 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message1" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message2" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client2") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client2") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt new file mode 100644 index 0000000000..8d8a2ff12c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt @@ -0,0 +1,83 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message1" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message2" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message3" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt new file mode 100644 index 0000000000..dbe9ebc13d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt @@ -0,0 +1,82 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message1" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message3" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt new file mode 100644 index 0000000000..db91f65323 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt @@ -0,0 +1,98 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message1" + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message2" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message3" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt new file mode 100644 index 0000000000..2f9653d000 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt @@ -0,0 +1,95 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message1" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message2" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message3" + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt new file mode 100644 index 0000000000..5006c59363 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt @@ -0,0 +1,83 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message1" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "test" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message3" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt new file mode 100644 index 0000000000..14fc69b797 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt @@ -0,0 +1,82 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message1" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "test" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message3" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/client.rpt new file mode 100644 index 0000000000..4cc383aeea --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/client.rpt @@ -0,0 +1,120 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +write "message" + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +write "message2" + +write notify PUBLISHED + +connect await PUBLISHED + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/two", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/server.rpt new file mode 100644 index 0000000000..099139ff74 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.subscribe.unfragmented/server.rpt @@ -0,0 +1,115 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +read "message2" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/two", 1) + .build() + .build()} + +connected + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/client.rpt new file mode 100644 index 0000000000..f15914b23e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/client.rpt @@ -0,0 +1,73 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +write "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/server.rpt new file mode 100644 index 0000000000..946782638d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message/server.rpt @@ -0,0 +1,71 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("AT_MOST_ONCE") + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.packet.too.large/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.packet.too.large/client.rpt new file mode 100644 index 0000000000..f02246b950 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.packet.too.large/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(9216) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.packet.too.large/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.packet.too.large/server.rpt new file mode 100644 index 0000000000..6543a0413b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.packet.too.large/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(9216) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/client.rpt new file mode 100644 index 0000000000..df76616097 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(0) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/server.rpt new file mode 100644 index 0000000000..58cb238a7b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(0) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/client.rpt new file mode 100644 index 0000000000..c7fbd6eb15 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/client.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities(WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + +write abort + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/server.rpt new file mode 100644 index 0000000000..6a569d5c82 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt new file mode 100644 index 0000000000..9212801e9c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt @@ -0,0 +1,69 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .build() + .build()} + +write "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt new file mode 100644 index 0000000000..5b3acac928 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt @@ -0,0 +1,68 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt new file mode 100644 index 0000000000..7375f857b6 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt @@ -0,0 +1,68 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("/sensors/1") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .userProperty("row1", "1") + .userProperty("row2", "2") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt new file mode 100644 index 0000000000..462f3d08af --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("/sensors/1") + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .userProperty("row1", "1") + .userProperty("row2", "2") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt new file mode 100644 index 0000000000..c0d527d820 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt @@ -0,0 +1,68 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("/sensors/1") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .userProperty("row1", "1") + .userProperty("row1", "2") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt new file mode 100644 index 0000000000..84b66de991 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("/sensors/1") + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .userProperty("row1", "1") + .userProperty("row1", "2") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt new file mode 100644 index 0000000000..c52c4f3dea --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("/sensors/1") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .userProperty("row", "1") + .build() + .build()} + +write "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt new file mode 100644 index 0000000000..d3925f6b6e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") + .topic("/sensors/1") + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .userProperty("row", "1") + .build() + .build()} + +read "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt new file mode 100644 index 0000000000..cb2fc4835a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt @@ -0,0 +1,135 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write abort +write notify SESSION_READY + + +connect await SESSION_READY + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} +connected + +write abort +write notify ABORTED + + +connect await ABORTED + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION_READY2 + +connect await SESSION_READY2 + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt new file mode 100644 index 0000000000..315c6dad7a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt @@ -0,0 +1,128 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +read aborted + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read aborted + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt new file mode 100644 index 0000000000..426e3aa983 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt @@ -0,0 +1,136 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify FIRST_CONNECTED + +read closed +write close + +connect await FIRST_CONNECTED + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} +connected + +write close +read closed + +write notify DISCONNECTED + + +connect await DISCONNECTED + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify SESSION_READY2 + +connect await SESSION_READY2 + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt new file mode 100644 index 0000000000..45c66b0a18 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt @@ -0,0 +1,134 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read await CLIENT_TAKEOVER + +write close +read closed + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read closed +write close + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write notify CLIENT_TAKEOVER + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/client.rpt new file mode 100644 index 0000000000..d3980ce8ec --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/client.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +read aborted + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/server.rpt new file mode 100644 index 0000000000..62685691f2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/client.rpt new file mode 100644 index 0000000000..30750fea4a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(100) + .clientId("client-1") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(30) + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/server.rpt new file mode 100644 index 0000000000..1357014205 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/server.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(100) + .clientId("client-1") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(30) + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt new file mode 100644 index 0000000000..66bf8e17ec --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("one") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("one") + .build() + .build()} + +connected + +read zilla:data.empty diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt new file mode 100644 index 0000000000..d6679679de --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .clientId("one") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("one") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/client.rpt new file mode 100644 index 0000000000..a8cb8971ee --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/server.rpt new file mode 100644 index 0000000000..62685691f2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt new file mode 100644 index 0000000000..71958940b8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt @@ -0,0 +1,115 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write notify CLIENT_TAKEOVER + +read closed +write close + +write notify SESSION_READY + +connect await SESSION_READY + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write close +read closed + +connect await SESSION_READY + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.empty diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt new file mode 100644 index 0000000000..2110d50b65 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt @@ -0,0 +1,111 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read await CLIENT_TAKEOVER + +write close +read closed + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read closed +write close + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.empty +write notify CLIENT_TAKEOVER diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/client.rpt new file mode 100644 index 0000000000..08ea0b183e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +read zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .serverRef("mqtt-2.example.com:1883") + .build()} + +write aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/server.rpt new file mode 100644 index 0000000000..4e3e92d69f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +write zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .serverRef("mqtt-2.example.com:1883") + .build()} + +read abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/client.rpt new file mode 100644 index 0000000000..90137a930e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/client.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .serverRef("mqtt-2.example.com:1883") + .build()} + +write aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/server.rpt new file mode 100644 index 0000000000..c14f65f6a6 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:reset.ext ${mqtt:resetEx() + .typeId(zilla:id("mqtt")) + .serverRef("mqtt-2.example.com:1883") + .build()} + +read abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/client.rpt new file mode 100644 index 0000000000..b76c68e4a6 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/client.rpt @@ -0,0 +1,64 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/server.rpt new file mode 100644 index 0000000000..8fcf49a343 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/server.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/client.rpt new file mode 100644 index 0000000000..4feceda522 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/client.rpt @@ -0,0 +1,97 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("sensor/two", 2) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/server.rpt new file mode 100644 index 0000000000..14ceb06745 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/server.rpt @@ -0,0 +1,100 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("sensor/two", 2) + .build() + .build()} + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/client.rpt new file mode 100644 index 0000000000..5f7bc09f52 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/client.rpt @@ -0,0 +1,116 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("reply", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("reply", 1) + .build()} + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("reply", 1) + .build() + .build()} + +connected + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("command/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} +write "message1" +write flush + + +connect "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("command/two") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} +write "message2" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/server.rpt new file mode 100644 index 0000000000..b58de36912 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/server.rpt @@ -0,0 +1,111 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app1" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("reply", 1) + .build()} + +write ${mqtt:session() + .subscription("reply", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("reply", 1) + .build() + .build()} + +connected + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("command/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} +read "message1" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("command/two") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} +read "message2" + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt new file mode 100644 index 0000000000..6e5c555867 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt @@ -0,0 +1,69 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +read ${mqtt:session() + .subscription("sensor/one") + .build()} + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt new file mode 100644 index 0000000000..d4b61821c8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt @@ -0,0 +1,72 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +write ${mqtt:session() + .subscription("sensor/one") + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt new file mode 100644 index 0000000000..53c8246fc5 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt new file mode 100644 index 0000000000..0e77f8fadc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt @@ -0,0 +1,73 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt new file mode 100644 index 0000000000..1571dfd191 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt @@ -0,0 +1,102 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write notify UNSUBSCRIBE_ALL_FILTERS +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .build()} + +read ${mqtt:session() + .build()} + +write notify SESSION_FINISHED + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt new file mode 100644 index 0000000000..620a720865 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt @@ -0,0 +1,104 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +read await UNSUBSCRIBE_ALL_FILTERS +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write ${mqtt:session() + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt new file mode 100644 index 0000000000..cfc946a237 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt @@ -0,0 +1,93 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .build()} + +read ${mqtt:session() + .build()} + +write notify SESSION_READY + + +connect await SESSION_READY + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt new file mode 100644 index 0000000000..760c4355f6 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt @@ -0,0 +1,93 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write ${mqtt:session() + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt new file mode 100644 index 0000000000..b7155f5111 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt @@ -0,0 +1,84 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +read ${mqtt:session() + .build()} + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt new file mode 100644 index 0000000000..9d4cb9d6bd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt @@ -0,0 +1,85 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write await RECEIVED_SUBSCRIBE_OPEN +write ${mqtt:session() + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected +read notify RECEIVED_SUBSCRIBE_OPEN + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/client.rpt new file mode 100644 index 0000000000..84ccb407cc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/client.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .clientId("one") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("wills/one") + .format("TEXT") + .payload("client one session expired") + .build()} +write flush + +read zilla:data.empty + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/server.rpt new file mode 100644 index 0000000000..928eb52a5b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/server.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .clientId("one") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("one") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("wills/one") + .format("TEXT") + .payload("client one session expired") + .build()} + +write zilla:data.empty +write flush + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt new file mode 100644 index 0000000000..97ccd5bbf8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .clientId("one") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("wills/one") + .format("TEXT") + .payload("client one session expired") + .build()} +write flush + +read zilla:data.empty + +write close +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt new file mode 100644 index 0000000000..d434f0d92d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .clientId("one") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("one") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("wills/one") + .format("TEXT") + .payload("client one session expired") + .build()} + +write zilla:data.empty +write flush + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt new file mode 100644 index 0000000000..d28140fa3b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START", "WILL") + .clientId("one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +write ${mqtt:will() + .topic("wills/one") + .flags("RETAIN") + .format("TEXT") + .payload("client one session expired") + .build()} +write flush + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .qosMax(0) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("one") + .build() + .build()} + +read zilla:data.empty + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt new file mode 100644 index 0000000000..ceb3f834aa --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "half-duplex" +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START", "WILL") + .clientId("one") + .build() + .build()} + +connected + + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("WILL") + .build() + .build()} + +read ${mqtt:will() + .topic("wills/one") + .flags("RETAIN") + .format("TEXT") + .payload("client one session expired") + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("WILL", "CLEAN_START") + .qosMax(0) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("one") + .build() + .build()} + +write zilla:data.empty +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt new file mode 100644 index 0000000000..2b7df6d001 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt @@ -0,0 +1,87 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .flags("RETAIN") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt new file mode 100644 index 0000000000..68efdb3ecf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt @@ -0,0 +1,86 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .flags("RETAIN") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt new file mode 100644 index 0000000000..bf8dc91ac2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt @@ -0,0 +1,90 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt new file mode 100644 index 0000000000..2b5798a9b2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt @@ -0,0 +1,90 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("sensor/one") + .correlation("info") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt new file mode 100644 index 0000000000..30d28313a9 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt @@ -0,0 +1,89 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .userProperty("row1", "1") + .userProperty("row1", "2") + .build() + .build()} + + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt new file mode 100644 index 0000000000..3b6116c818 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt @@ -0,0 +1,88 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .userProperty("row1", "1") + .userProperty("row1", "2") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt new file mode 100644 index 0000000000..b45659cb77 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt @@ -0,0 +1,85 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt new file mode 100644 index 0000000000..50a3045682 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt @@ -0,0 +1,86 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.invalid.affinity/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.invalid.affinity/client.rpt new file mode 100644 index 0000000000..e8cb3e6508 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.invalid.affinity/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc1 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build() + .build()} + +connect aborted + + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc1 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connect aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.invalid.affinity/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.invalid.affinity/server.rpt new file mode 100644 index 0000000000..e896a47016 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.invalid.affinity/server.rpt @@ -0,0 +1,23 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +rejected + +rejected \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt new file mode 100644 index 0000000000..c0bc2759ca --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt @@ -0,0 +1,111 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build() + .build()} + +connected +write notify RECEIVED_SUBSCRIBE_OPEN + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message2" + + +connect await RECEIVED_SUBSCRIBE_OPEN + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +write "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt new file mode 100644 index 0000000000..cddcae8682 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt @@ -0,0 +1,106 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "NO_LOCAL") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +write "message2" +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt new file mode 100644 index 0000000000..ea318306af --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt @@ -0,0 +1,138 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc1 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client-1") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client-1") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc1 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client-1") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .format("TEXT") + .build() + .build()} + +write "message" +write flush +write notify SENT_RETAIN_DATA + + +connect await SENT_RETAIN_DATA + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc2 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client-2") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client-2") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE2 + + +connect await RECEIVED_SESSION_STATE2 + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc2 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-2") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt new file mode 100644 index 0000000000..755712b684 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt @@ -0,0 +1,125 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client-1") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client-1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client-1") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .format("TEXT") + .build() + .build()} + +read "message" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client-2") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client-2") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client-2") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt new file mode 100644 index 0000000000..0c193373c8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt @@ -0,0 +1,148 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc1 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client1") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client1") + .build() + .build()} + + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc1 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client1") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .format("TEXT") + .build() + .build()} + +write "message" +write flush +write notify SENT_RETAIN_DATA + +connect await SENT_RETAIN_DATA + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc2 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client2") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client2") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} +read notify RECEIVED_SESSION_STATE2 + + +connect await RECEIVED_SESSION_STATE2 + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:affinity 0xc2 + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client2") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt new file mode 100644 index 0000000000..2c5e931635 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt @@ -0,0 +1,136 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client1") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client1") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client1") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .flags("RETAIN") + .format("TEXT") + .build() + .build()} + +read "message" + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client2") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client2") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client2") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt new file mode 100644 index 0000000000..7fe6c75d40 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt @@ -0,0 +1,112 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/+/#", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/+/#", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 2) + .build()} + +read ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 2) + .build()} + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/#", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/+/#", 1) + .filter("sensor/+/1", 2) + .build() + .build()} + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one/1") + .subscriptionId(1) + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt new file mode 100644 index 0000000000..c3f3bed38e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt @@ -0,0 +1,113 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/+/#", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/+/#", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 2) + .build()} + +write ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 2) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/#", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/+/#", 1) + .filter("sensor/+/1", 2) + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one/1") + .subscriptionId(1) + .subscriptionId(2) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt new file mode 100644 index 0000000000..25304564a4 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt @@ -0,0 +1,86 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/+", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/+", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt new file mode 100644 index 0000000000..3a88d85ead --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt @@ -0,0 +1,86 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/+", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/+", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt new file mode 100644 index 0000000000..01678ad7a6 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt @@ -0,0 +1,109 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +write "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt new file mode 100644 index 0000000000..7da984932b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt @@ -0,0 +1,105 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +write "message" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +read "message" + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/client.rpt new file mode 100644 index 0000000000..a1974837f0 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/client.rpt @@ -0,0 +1,110 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +write "message" +write flush + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/server.rpt new file mode 100644 index 0000000000..7da984932b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/server.rpt @@ -0,0 +1,105 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +write "message" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .format("TEXT") + .build() + .build()} +read "message" + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/client.rpt new file mode 100644 index 0000000000..9d460c24da --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/client.rpt @@ -0,0 +1,109 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} +read notify RECEIVED_NEW_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} +read "message" + +write await RECEIVED_NEW_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("sensor/two", 2) + .build() + .build()} + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/server.rpt new file mode 100644 index 0000000000..729f9790fc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/server.rpt @@ -0,0 +1,109 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("sensor/two", 2) + .build() + .build()} + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/two") + .subscriptionId(2) + .format("TEXT") + .build() + .build()} +write "message" +write flush \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/client.rpt new file mode 100644 index 0000000000..23f920f17a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/server.rpt new file mode 100644 index 0000000000..3167305bbe --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/client.rpt new file mode 100644 index 0000000000..4a57d637db --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/server.rpt new file mode 100644 index 0000000000..dbb15859eb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt new file mode 100644 index 0000000000..b3ba629994 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt new file mode 100644 index 0000000000..fffe14919d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt new file mode 100644 index 0000000000..fda2157214 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt @@ -0,0 +1,87 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .flags("RETAIN") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt new file mode 100644 index 0000000000..c2e06f5318 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt @@ -0,0 +1,87 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED", "RETAIN_AS_PUBLISHED") + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .topic("sensor/one") + .flags("RETAIN") + .subscriptionId(1) + .format("TEXT") + .build() + .build()} + +write "message" +write flush diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt new file mode 100644 index 0000000000..1894b9768e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/#", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt new file mode 100644 index 0000000000..8c743bf6bd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt @@ -0,0 +1,74 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/#", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt new file mode 100644 index 0000000000..fcd6c91678 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/+/1/#", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/+/1/#", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/1/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt new file mode 100644 index 0000000000..c03d44bf10 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt @@ -0,0 +1,74 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/+/1/#", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/+/1/#", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/1/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt new file mode 100644 index 0000000000..70eff1aca7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt new file mode 100644 index 0000000000..78e751b79a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt @@ -0,0 +1,74 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt new file mode 100644 index 0000000000..f33e1f91fe --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/+", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/+", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt new file mode 100644 index 0000000000..9fb6d03c6c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/+", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/+", 1) + .build()} +write flush + + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt new file mode 100644 index 0000000000..ed53019dbb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt @@ -0,0 +1,75 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/+/+", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/+/+", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/+", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt new file mode 100644 index 0000000000..41af57518e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt @@ -0,0 +1,74 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/+/+", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/+/+", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/+", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt new file mode 100644 index 0000000000..28fb765733 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt new file mode 100644 index 0000000000..44d030c4a7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt @@ -0,0 +1,79 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt new file mode 100644 index 0000000000..f319d2c650 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("device/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt new file mode 100644 index 0000000000..c253604fbf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt @@ -0,0 +1,77 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("device/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt new file mode 100644 index 0000000000..5255ad1a10 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/#", 1) + .filter("device/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt new file mode 100644 index 0000000000..3628e544e0 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt @@ -0,0 +1,77 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/#", 1) + .filter("device/#", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt new file mode 100644 index 0000000000..56864dabda --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt @@ -0,0 +1,103 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} +read notify RECEIVED_NEW_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write await RECEIVED_NEW_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("sensor/two", 2) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt new file mode 100644 index 0000000000..9c873daaea --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt @@ -0,0 +1,101 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 2) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("sensor/two", 2) + .build() + .build()} + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt new file mode 100644 index 0000000000..2b2003ecf1 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt @@ -0,0 +1,103 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/#", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 2) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 2) + .build()} +read notify RECEIVED_NEW_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/#", 1) + .build() + .build()} + +connected + +write await RECEIVED_NEW_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/#", 1) + .filter("device/#", 2) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt new file mode 100644 index 0000000000..e966263783 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt @@ -0,0 +1,101 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/#", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 2) + .build()} + +write ${mqtt:session() + .subscription("sensor/#", 1) + .subscription("device/#", 2) + .build()} +write flush + + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/#", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/#", 1) + .filter("device/#", 2) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt new file mode 100644 index 0000000000..b11c1e4ee9 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt @@ -0,0 +1,103 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 2) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 2) + .build()} +read notify RECEIVED_NEW_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write await RECEIVED_NEW_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("device/#", 2) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt new file mode 100644 index 0000000000..c8b5ff2b20 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt @@ -0,0 +1,100 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 2) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("device/#", 2) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/one", 1) + .filter("device/#", 2) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/client.rpt new file mode 100644 index 0000000000..f04d809380 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/client.rpt @@ -0,0 +1,77 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1, 0) + .subscription("sensor/two", 1, 135) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/server.rpt new file mode 100644 index 0000000000..0248734261 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/server.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1, 135) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt new file mode 100644 index 0000000000..0840ca0c91 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 1) + .build()} +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/#", 1) + .filter("sensor/+/1", 1) + .build() + .build()} + +connected diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt new file mode 100644 index 0000000000..5fe13e09ce --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt @@ -0,0 +1,78 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/+/#", 1) + .subscription("sensor/+/1", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/+/#", 1) + .filter("sensor/+/1", 1) + .build() + .build()} + +connected + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt new file mode 100644 index 0000000000..1eb10f6e72 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt @@ -0,0 +1,95 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .build()} +write flush + +read ${mqtt:session() + .build()} + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt new file mode 100644 index 0000000000..cc53c1bc79 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt @@ -0,0 +1,94 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write ${mqtt:session() + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt new file mode 100644 index 0000000000..088b00bdbd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt @@ -0,0 +1,99 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .build()} +write flush + +read ${mqtt:session() + .build()} +read notify RECEIVED_NEW_SESSION_STATE + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +write await RECEIVED_NEW_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt new file mode 100644 index 0000000000..3eb936e39b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt @@ -0,0 +1,97 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write ${mqtt:session() + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt new file mode 100644 index 0000000000..14471265ea --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt @@ -0,0 +1,127 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/two", 1) + .build()} + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} + +write notify SUBSCRIBED + +connect await SUBSCRIBED + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +write "message" + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt new file mode 100644 index 0000000000..fe80f7bfae --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt @@ -0,0 +1,120 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/two") + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .build() + .build()} + +read "message" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt new file mode 100644 index 0000000000..54eb445aa6 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt @@ -0,0 +1,103 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +read notify RECEIVED_NEW_SESSION_STATE + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +write await RECEIVED_NEW_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt new file mode 100644 index 0000000000..c545952949 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt @@ -0,0 +1,100 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/two", 1) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/client.rpt new file mode 100644 index 0000000000..5f9f15fc2e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/client.rpt @@ -0,0 +1,101 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +read notify RECEIVED_SESSION_STATE + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +write ${mqtt:session() + .build()} +write flush + +read ${mqtt:session() + .subscription("sensor/two", 1, 135) + .build()} +read notify RECEIVED_NEW_SESSION_STATE + +connect await RECEIVED_SESSION_STATE + "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +write await RECEIVED_NEW_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/server.rpt new file mode 100644 index 0000000000..adcf408f35 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/server.rpt @@ -0,0 +1,99 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .qosMax(2) + .packetSizeMax(66560) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} + +write ${mqtt:session() + .subscription("sensor/one", 1) + .subscription("sensor/two", 1) + .build()} +write flush + +read zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .session() + .kind("STATE") + .build() + .build()} + +read ${mqtt:session() + .build()} + +write ${mqtt:session() + .subscription("sensor/two", 1, 135) + .build()} +write flush + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .clientId("client") + .filter("sensor/one", 1) + .filter("sensor/two", 1) + .build() + .build()} + +connected + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .subscribe() + .filter("sensor/two", 1) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/client.rpt new file mode 100644 index 0000000000..6885400b6d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/client.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/server.rpt new file mode 100644 index 0000000000..dd011faafc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.abort/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/client.rpt new file mode 100644 index 0000000000..2fbda6f599 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/client.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/server.rpt new file mode 100644 index 0000000000..6cdf70836b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.close/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/client.rpt new file mode 100644 index 0000000000..aff52eb2c4 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/client.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/server.rpt new file mode 100644 index 0000000000..ad5d2b332c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/client.sent.reset/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.delegate.connack.properties/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.delegate.connack.properties/client.rpt new file mode 100644 index 0000000000..0272fd6bb4 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.delegate.connack.properties/client.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x23] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x20] # properties + [0x27] 50 # maximum packet size = 50 + [0x25 0x00] # retain unavailable + [0x2a 0x00] # shared subscription unavailable + [0x29 0x00] # subscription identifiers unavailable + [0x28 0x00] # wildcard subscription unavailable + [0x24 0x00] # maximum qos = at most once + [0x22] 0s # topic alias maximum = 0 + [0x13] 1s # keep alive = 1s + [0x12 0x00 0x08] "client-1" # assigned clientId + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.delegate.connack.properties/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.delegate.connack.properties/server.rpt new file mode 100644 index 0000000000..0a7638048e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.delegate.connack.properties/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x23] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x20] # properties + [0x27] 50 # maximum packet size = 50 + [0x25 0x00] # retain unavailable + [0x2a 0x00] # shared subscription unavailable + [0x29 0x00] # subscription identifiers unavailable + [0x28 0x00] # wildcard subscription unavailable + [0x24 0x00] # maximum qos = at most once + [0x22] 0s # topic alias maximum = 0 + [0x13] 1s # keep alive = 1s + [0x12 0x00 0x08] "client-1" # assigned clientId + diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.authentication.method/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.flags/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.invalid.protocol.version/server.rpt diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/client.rpt new file mode 100644 index 0000000000..d7944ac3e7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties = maximum packet size + [0x27] 50 # maximum packet size = 50 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 50 # maximum packet size = 50 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/server.rpt new file mode 100644 index 0000000000..ad9b156305 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.exceeded/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties = maximum packet size + [0x27] 50 # maximum packet size = 50 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 50 # maximum packet size = 50 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt new file mode 100644 index 0000000000..dddff030bd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/client.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties = maximum packet size + [0x27 0x00 0x32] # maximum packet size = 50 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x27] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x13] # properties + [0x0b 0x01] # subscription id = 1 + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt new file mode 100644 index 0000000000..b0bde6dc23 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.max.packet.size.server.ignores.exceeding.publish.packet/server.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties = maximum packet size + [0x27 0x00 0x32] # maximum packet size = 50 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x27] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x13] # properties + [0x0b 0x01] # subscription id = 1 + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/client.rpt new file mode 100644 index 0000000000..e296e3aa88 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/server.rpt new file mode 100644 index 0000000000..badb4b4bdf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.maximum.qos.0/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.connack/client.rpt new file mode 100644 index 0000000000..2c314341a5 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.connack/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x84] # reason code = unsupported protocol + [0x00] # properties = none + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.connack/server.rpt new file mode 100644 index 0000000000..cb13d52772 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.connack/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x84] # reason code = unsupported protocol + [0x00] # properties = none + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.disconnect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.disconnect/client.rpt new file mode 100644 index 0000000000..173591b764 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.disconnect/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code = success + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read notify RECEIVED_SESSION_STATE +read [0xe0 0x02] # DISCONNECT + [0x81] # malformed packet + [0x00] # properties = none + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.disconnect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.disconnect/server.rpt new file mode 100644 index 0000000000..9d836c1473 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.non.successful.disconnect/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code = success + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write await RECEIVED_SESSION_STATE +write [0xe0 0x02] # DISCONNECT + [0x81] # malformed packet + [0x00] # properties = none + +read abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.failed/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.failed/client.rpt new file mode 100644 index 0000000000..47b6b7eeba --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.failed/client.rpt @@ -0,0 +1,33 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x25] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x42] # flags = password, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x10] "Bearer INCORRECT" # password + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.failed/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.failed/server.rpt new file mode 100644 index 0000000000..1c62c0f0bf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.failed/server.rpt @@ -0,0 +1,35 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x25] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x42] # flags = password, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x10] "Bearer INCORRECT" # password + + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.successful/client.rpt new file mode 100644 index 0000000000..b9b5d32130 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.successful/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x21] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x42] # flags = password, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x0c] "Bearer TOKEN" # password + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.successful/server.rpt new file mode 100644 index 0000000000..57871900b2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.password.authentication.successful/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x21] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x42] # flags = password, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x0c] "Bearer TOKEN" # password + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.missing.client.id/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.other.packet.before.connect/server.rpt diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.packet.too.large/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.packet.too.large/client.rpt new file mode 100644 index 0000000000..6a8b2df528 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.packet.too.large/client.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0xff 0x7f] # CONNECT, remaining length = 16383 + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x00] # properties + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0xdf 0x3f] ${mqtt:randomBytes(16351)} # will payload + +read [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x95] # reason = packet too large + [0x00] # properties = none + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.packet.too.large/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.packet.too.large/server.rpt new file mode 100644 index 0000000000..5c7427a967 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.packet.too.large/server.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0xff 0x7f] # CONNECT, remaining length = 16383 + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x00] # properties + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0xdf 0x3f] [0..16351] # will payload + +write [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x95] # reason = packet too large + [0x00] # properties = none + +write close +read closed diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.flag.no.password/server.rpt diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/client.rpt new file mode 100644 index 0000000000..26db218806 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x27] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x82] # flags = username, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x08] "username" # username + [0x00 0x08] "password" # password + +read [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x81] # reason = malformed packet + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/server.rpt new file mode 100644 index 0000000000..32c8cdfc7d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.password.no.password.flag/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x27] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x82] # flags = username, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x08] "username" # username + [0x00 0x08] "password" # password + +write [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x81] # reason = malformed packet + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/client.rpt new file mode 100644 index 0000000000..4c1ac6cfc0 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0xe0 0x02] # DISCONNECT + [0x82] # reason = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/server.rpt new file mode 100644 index 0000000000..8a49f9d9ab --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.second.connect/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0xe0 0x02] # DISCONNECT + [0x82] # reason = protocol error + [0x00] # properties = none + +write close diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.topic.alias.maximum.repeated/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.missing/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.username.flag.only/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.payload.missing/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.properties.missing/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.retain.not.supported/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.reject.will.topic.missing/server.rpt diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/client.rpt new file mode 100644 index 0000000000..3f273dbfaf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x25 0x00] # retain unavailable + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/server.rpt new file mode 100644 index 0000000000..915ca3ba71 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.retain.not.supported/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x25 0x00] # retain unavailable diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/client.rpt new file mode 100644 index 0000000000..43e6312ee1 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/client.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x0d] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x00] # client id + +read [0x20 0x11] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x0e] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x12 0x00 0x06] "client" # assigned clientId diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/server.rpt new file mode 100644 index 0000000000..aaa6880354 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.assigned.client.id/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +property assignedClientId "123e4567-e89b-42d3-a456-556642440000" + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x0d] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x00] # client id + +write [0x20 0x11] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x0e] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x12 0x00 0x06] "client" # assigned clientId diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/client.rpt new file mode 100644 index 0000000000..a60102b57c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/client.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties = server keep alive + [0x27] 66560 # maximum packet size = 66560 + [0x13] 10s # server keep alive = 10s + +read await WAIT_2_SECONDS + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/server.rpt new file mode 100644 index 0000000000..8f4267357c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.server.defined.keep.alive/server.rpt @@ -0,0 +1,40 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties = server keep alive + [0x27] 66560 # maximum packet size = 66560 + [0x13] 10s # server keep alive = 10s + +write notify WAIT_2_SECONDS diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/client.rpt new file mode 100644 index 0000000000..728ae4003a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/server.rpt new file mode 100644 index 0000000000..1ed4dd5906 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.subscribe.unfragmented/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/client.rpt new file mode 100644 index 0000000000..ab94edaee7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name +write [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/server.rpt new file mode 100644 index 0000000000..7eeb5401f2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful.fragmented/server.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/client.rpt new file mode 100644 index 0000000000..05646c53a2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/server.rpt new file mode 100644 index 0000000000..7eeb5401f2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.successful/server.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.timeout.before.connect/server.rpt diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.failed/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.failed/client.rpt new file mode 100644 index 0000000000..b95a982110 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.failed/client.rpt @@ -0,0 +1,33 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x25] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x82] # flags = username, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x10] "Bearer INCORRECT" # username + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.failed/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.failed/server.rpt new file mode 100644 index 0000000000..e9113e3ce0 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.failed/server.rpt @@ -0,0 +1,34 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x25] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x82] # flags = username, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x10] "Bearer INCORRECT" # username + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.successful/client.rpt new file mode 100644 index 0000000000..61b54afa2f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.successful/client.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x21] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x82] # flags = username, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x0c] "Bearer TOKEN" # username + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.successful/server.rpt new file mode 100644 index 0000000000..4e6ff6a617 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.username.authentication.successful/server.rpt @@ -0,0 +1,38 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x21] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x82] # flags = username, clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + [0x00 0x0c] "Bearer TOKEN" # username + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.invalid.will.qos/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.1.without.will.flag/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.qos.2.without.will.flag/server.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/client.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/client.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/client.rpt diff --git a/incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/server.rpt similarity index 100% rename from incubator/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/server.rpt rename to specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/connect.will.reject.will.retain.without.will.flag/server.rpt diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/client.rpt new file mode 100644 index 0000000000..e1fd8c7e1b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/client.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x02] # DISCONNECT + [0x8d] # reason = keep alive timeout + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/server.rpt new file mode 100644 index 0000000000..3990ba344c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.keep.alive.timeout/server.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x02] # DISCONNECT + [0x8d] # reason = keep alive timeout + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.subscribe.and.publish/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.subscribe.and.publish/client.rpt new file mode 100644 index 0000000000..adaf18979d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.subscribe.and.publish/client.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x14] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x00] # properties + "message" # payload + +write [0xe0 0x02] # DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.subscribe.and.publish/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.subscribe.and.publish/server.rpt new file mode 100644 index 0000000000..f283dd141c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.after.subscribe.and.publish/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x14] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x00] # properties + "message" # payload + +read [0xe0 0x02] # DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.invalid.session.expiry/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.invalid.session.expiry/client.rpt new file mode 100644 index 0000000000..d5b670b0cc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.invalid.session.expiry/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x07] # DISCONNECT + [0x00] # normal disconnect + [0x05] # properties = none + [0x11] 1 # session expiry = 30 + +read [0xe0 0x02] # DISCONNECT + [0x82] # reason = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.invalid.session.expiry/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.invalid.session.expiry/server.rpt new file mode 100644 index 0000000000..ef44a24f56 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.invalid.session.expiry/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x07] # DISCONNECT + [0x00] # normal disconnect + [0x05] # properties = none + [0x11] 1 # session expiry = 30 + +write [0xe0 0x02] # DISCONNECT + [0x82] # reason = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.no.reasoncode.no.properties/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.no.reasoncode.no.properties/client.rpt new file mode 100644 index 0000000000..1c0ba53c63 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.no.reasoncode.no.properties/client.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x00] # DISCONNECT + +write close +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.no.reasoncode.no.properties/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.no.reasoncode.no.properties/server.rpt new file mode 100644 index 0000000000..6261500d74 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.no.reasoncode.no.properties/server.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x00] # DISCONNECT + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/client.rpt new file mode 100644 index 0000000000..19450a379d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/client.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0xe1 0x02] # malformed DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + +read [0xe0 0x02] # malformed DISCONNECT + [0x81] # malformed packet + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/server.rpt new file mode 100644 index 0000000000..4d2e89d6ca --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect.reject.invalid.fixed.header.flags/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0xe1 0x02] # malformed DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + +write [0xe0 0x02] # DISCONNECT + [0x81] # malformed packet + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/client.rpt new file mode 100644 index 0000000000..79d7bff1ea --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x02] # DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + +write close +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/server.rpt new file mode 100644 index 0000000000..a32c69a84d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/disconnect/server.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x02] # DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/client.rpt new file mode 100644 index 0000000000..1da22ab03f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read await WAIT_1_SECOND + +write [0xc0 0x00] # PINGREQ + +read [0xd0 0x00] # PINGRESP + +read await WAIT_1_SECOND2 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/server.rpt new file mode 100644 index 0000000000..68e12ef631 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.keep.alive/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write notify WAIT_1_SECOND + +read [0xc0 0x00] # PINGREQ + +write [0xd0 0x00] # PINGRESP + +write notify WAIT_1_SECOND2 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.no.pingresp/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.no.pingresp/client.rpt new file mode 100644 index 0000000000..b54b872cda --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.no.pingresp/client.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x13] 1s # keep alive = 1s + +write [0xc0 0x00] # PINGREQ + +write abort diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.no.pingresp/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.no.pingresp/server.rpt new file mode 100644 index 0000000000..03208ff58b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.no.pingresp/server.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x13] 1s # keep alive = 1s + +read [0xc0 0x00] # PINGREQ + +read aborted diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.server.override.keep.alive/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.server.override.keep.alive/client.rpt new file mode 100644 index 0000000000..8e0554766d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.server.override.keep.alive/client.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x13] 1s # keep alive = 1s + +write [0xc0 0x00] # PINGREQ + +read [0xd0 0x00] # PINGRESP + +write [0xc0 0x00] # PINGREQ + +read [0xd0 0x00] # PINGRESP diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.server.override.keep.alive/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.server.override.keep.alive/server.rpt new file mode 100644 index 0000000000..08899b5c28 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping.server.override.keep.alive/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x13] 1s # keep alive = 1s + +read [0xc0 0x00] # PINGREQ + +write [0xd0 0x00] # PINGRESP + +read [0xc0 0x00] # PINGREQ + +write [0xd0 0x00] # PINGRESP diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/client.rpt new file mode 100644 index 0000000000..e6fa483bfb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/client.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0xc0 0x00] # PINGREQ + +read [0xd0 0x00] # PINGRESP diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/server.rpt new file mode 100644 index 0000000000..97dd222d7f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/ping/server.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0xc0 0x00] # PINGREQ + +write [0xd0 0x00] # PINGRESP diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/client.rpt new file mode 100644 index 0000000000..a2414dec40 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/client.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x0d] # PUBLISH flags = at-most-once + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/server.rpt new file mode 100644 index 0000000000..794041b35f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.message/server.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x0d] # PUBLISH flags = at-most-once + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/client.rpt new file mode 100644 index 0000000000..d860770948 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/client.rpt @@ -0,0 +1,41 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x31 0x0d] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/server.rpt new file mode 100644 index 0000000000..e2c51a72f6 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.empty.retained.message/server.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x31 0x0d] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/client.rpt new file mode 100644 index 0000000000..6b0f47417c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +write [0x30 0x17] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/server.rpt new file mode 100644 index 0000000000..4c3f098582 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.message.with.topic.alias/server.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +read [0x30 0x17] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/client.rpt new file mode 100644 index 0000000000..4d8a3ad977 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/client.rpt @@ -0,0 +1,85 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + +connected + +write [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + +write notify PUBLISHED + +connect await PUBLISHED + "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + +connected + +write [0x10 0x17] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client2" # client id + +read [0x20 0x06] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/server.rpt new file mode 100644 index 0000000000..e7aaa2b47b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.no.carry.over.topic.alias/server.rpt @@ -0,0 +1,81 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted +connected + +read [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + + +accepted +connected + +read [0x10 0x17] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client2" # client id + +write [0x20 0x06] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/client.rpt new file mode 100644 index 0000000000..ab309028ed --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/client.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x02] # topic alias maximum = 2 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 2s # topic alias maximum = 2 + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x03] # properties + [0x23 0x00 0x02] # topic alias = 2 + "message2" # payload + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x02] # topic alias = 2 + "message4" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/server.rpt new file mode 100644 index 0000000000..d8e29935cf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.distinct/server.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x02] # topic alias maximum = 2 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 2s # topic alias maximum = 2 + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x03] # properties + [0x23 0x00 0x02] # topic alias = 2 + "message2" # payload + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x02] # topic alias = 2 + "message4" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/client.rpt new file mode 100644 index 0000000000..2e9d8afc44 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/client.rpt @@ -0,0 +1,88 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + +write notify PUBLISHED + +connect await PUBLISHED + "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x17] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x07] "client2" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/server.rpt new file mode 100644 index 0000000000..f43b342306 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.invalid.scope/server.rpt @@ -0,0 +1,83 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + + +accepted +connected + +read [0x10 0x17] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x07] "client2" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/client.rpt new file mode 100644 index 0000000000..573328e173 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/server.rpt new file mode 100644 index 0000000000..b9154917d0 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.repeated/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/client.rpt new file mode 100644 index 0000000000..8a39558db3 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + +write [0x30 0x0e] # PUBLISH + [0x00 0x00] # empty topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/server.rpt new file mode 100644 index 0000000000..5d627dd331 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.messages.with.topic.alias.replaced/server.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message1" # payload + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message2" # payload + +read [0x30 0x0e] # PUBLISH + [0x00 0x00] # topic name = empty + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message3" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/client.rpt new file mode 100644 index 0000000000..9c790a6c1f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message1" # payload + [0x30 0x11] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "test" # payload + [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message3" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/server.rpt new file mode 100644 index 0000000000..d876b2b6c1 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.unfragmented/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message1" # payload + [0x30 0x11] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "test" # payload + [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message3" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/client.rpt new file mode 100644 index 0000000000..96c43ea885 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message1" # payload + +write [0x30 0x11] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "test" # payload + +write notify PUBLISHED_MESSAGE_TWO +write await PUBLISH_MESSAGE_THREE + +write [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message3" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/server.rpt new file mode 100644 index 0000000000..8d2e633257 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages.with.delay/server.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message1" # payload + +read [0x30 0x11] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "test" # payload + +read [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message3" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/client.rpt new file mode 100644 index 0000000000..a694f7cdee --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message1" # payload + +write [0x30 0x11] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "test" # payload + +write [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message3" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/server.rpt new file mode 100644 index 0000000000..8d2e633257 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.multiple.messages/server.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message1" # payload + +read [0x30 0x11] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "test" # payload + +read [0x30 0x15] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message3" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/client.rpt new file mode 100644 index 0000000000..50d990ab95 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/client.rpt @@ -0,0 +1,66 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x39] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + [0x30 0x3a] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message2" # payload + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/server.rpt new file mode 100644 index 0000000000..49d54fcd5b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message.subscribe.unfragmented/server.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x39] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/client.rpt new file mode 100644 index 0000000000..91f275b965 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x39] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/server.rpt new file mode 100644 index 0000000000..436e7daad3 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.one.message/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x39] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/client.rpt new file mode 100644 index 0000000000..fa4565b101 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/client.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x31 0x28] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x12] # properties + [0x0b 0x01] # subscription id = 1 + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x0a] "text/plain" # content type + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x81] # reason = malformed packet + [0x00] # properties = none + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/server.rpt new file mode 100644 index 0000000000..6a78f222dc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.client.sent.subscription.id/server.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x31 0x28] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x12] # properties + [0x0b 0x01] # subscription id = 1 + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x0a] "text/plain" # content type + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x81] # reason = malformed packet + [0x00] # properties = none + +write close +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/client.rpt new file mode 100644 index 0000000000..ffa3fd696a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x36] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + [0xfe 0xfe 0xff 0xff] # payload + +read [0xe0 0x02] # DISCONNECT + [0x99] # payload format invalid + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/server.rpt new file mode 100644 index 0000000000..2412c0df9f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.invalid.payload.format/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x36] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + [0xfe 0xfe 0xff 0xff] # payload + +write [0xe0 0x02] # DISCONNECT + [0x99] # payload format invalid + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.packet.too.large/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.packet.too.large/client.rpt new file mode 100644 index 0000000000..04c7b54dbc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.packet.too.large/client.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 9216 # maximum packet size = 9216 + +write [0x30 0xff 0x7f] # PUBLISH, remaining length = 16383 + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + ${mqtt:randomBytes(16326)} # payload + +read [0xe0 0x02] # disconnect header + [0x95] # reason = packet too large + [0x00] # properties = none + +read closed +write close + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.packet.too.large/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.packet.too.large/server.rpt new file mode 100644 index 0000000000..863be0b74c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.packet.too.large/server.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 9216 # maximum packet size = 9216 + +read [0x30 0xff 0x7f] # PUBLISH, remaining length = 16383 + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + [0..16326] # payload + +write [0xe0 0x02] # disconnect header + [0x95] # reason = packet too large + [0x00] # properties = none + +write close +read closed + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/client.rpt new file mode 100644 index 0000000000..fe2d55b49f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/client.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x3b] # PUBLISH, qos = at most once + [0x00 0x0a] "sensor/one" # topic name + [0x00 0x01] # packet id = 1 + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/server.rpt new file mode 100644 index 0000000000..345786e4d7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos0.with.packet.id/server.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x3b] # PUBLISH, qos = at most once + [0x00 0x0a] "sensor/one" # topic name + [0x00 0x01] # packet id = 1 + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/client.rpt new file mode 100644 index 0000000000..a300b9d0eb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/client.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + +write [0x32 0x3b] # PUBLISH, qos = at least once + [0x00 0x0a] "sensor/one" # topic name + [0x00 0x01] # packet id = 1 + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x9b] # disconnect = QoS not supported + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/server.rpt new file mode 100644 index 0000000000..f98707b20f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.not.supported/server.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + +read [0x32 0x3b] # PUBLISH, qos = at least once + [0x00 0x0a] "sensor/one" # topic name + [0x00 0x01] # packet id = 1 + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x9b] # disconnect = QoS not supported + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/client.rpt new file mode 100644 index 0000000000..5e94229103 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x32 0x39] # PUBLISH, qos = at least once + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/server.rpt new file mode 100644 index 0000000000..d18a86c6ce --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos1.without.packet.id/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x32 0x39] # PUBLISH, qos = at least once + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/client.rpt new file mode 100644 index 0000000000..99501dc869 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/client.rpt @@ -0,0 +1,54 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + +write [0x34 0x3b] # PUBLISH, qos = exactly once + [0x00 0x0a] "sensor/one" # topic name + [0x00 0x01] # packet id = 1 + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x9b] # disconnect = QoS not supported + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/server.rpt new file mode 100644 index 0000000000..15c93e65ca --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.not.supported/server.rpt @@ -0,0 +1,55 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + +read [0x34 0x3b] # PUBLISH, qos = exactly once + [0x00 0x0a] "sensor/one" # topic name + [0x00 0x01] # packet id = 1 + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x9b] # disconnect = QoS not supported + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/client.rpt new file mode 100644 index 0000000000..865f19c5fc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x34 0x39] # PUBLISH, qos = exactly once + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/server.rpt new file mode 100644 index 0000000000..12b201a50f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.qos2.without.packet.id/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x34 0x39] # PUBLISH, qos = exactly once + [0x00 0x0a] "sensor/one" # topic name + [0x25] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/client.rpt new file mode 100644 index 0000000000..a62e263d13 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x25 0x00] # retain unavailable + +write [0x31 0x26] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x12] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x0a] "text/plain" # content type + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x9a] # disconnect = retain not supported + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/server.rpt new file mode 100644 index 0000000000..00308505a8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.retain.not.supported/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x25 0x00] # retain unavailable + +read [0x31 0x26] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x12] # properties + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x0a] "text/plain" # content type + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x9a] # disconnect = retain not supported + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/client.rpt new file mode 100644 index 0000000000..861eb55fdf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x17] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x94] # disconnect = topic alias invalid + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/server.rpt new file mode 100644 index 0000000000..5dd6de1f31 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.exceeds.maximum/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x17] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x03] # properties + [0x23 0x00 0x01] # topic alias = 1 + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x94] # disconnect = topic alias invalid + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/client.rpt new file mode 100644 index 0000000000..7aa1203da8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/client.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +read [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +write [0x30 0x1a] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x06] # properties + [0x23 0x00 0x01] # topic alias = 1 + [0x23 0x00 0x01] # topic alias = 1 + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/server.rpt new file mode 100644 index 0000000000..c0932a2468 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.reject.topic.alias.repeated/server.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x16] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x03] # properties + [0x22 0x00 0x01] # topic alias maximum = 1 + [0x00 0x06] "client" # client id + +write [0x20 0x0b] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x08] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x22] 1s # topic alias maximum = 1 + +read [0x30 0x1a] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x06] # properties + [0x23 0x00 0x01] # topic alias = 1 + [0x23 0x00 0x01] # topic alias = 1 + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/client.rpt new file mode 100644 index 0000000000..634a3e994d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x31 0x14] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/server.rpt new file mode 100644 index 0000000000..05be6f0398 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.retained/server.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x31 0x14] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x00] # properties + "message" # payload + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/client.rpt new file mode 100644 index 0000000000..d40221b8e3 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x15] # PUBLISH + [0x00 0x0b] "sensor/none" # topic name + [0x00] # properties = none + "message" # payload + +read [0xe0 0x02] # disconnect header + [0x90] # DISCONNECT = topic name invalid + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/server.rpt new file mode 100644 index 0000000000..69db05a2ac --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.topic.not.routed/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x15] # PUBLISH + [0x00 0x0b] "sensor/none" # topic name + [0x00] # properties = none + "message" # payload + +write [0xe0 0x02] # disconnect header + [0x90] # DISCONNECT = topic name invalid + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/client.rpt new file mode 100644 index 0000000000..f3bd76a134 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x36] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x4a] # PUBLISH + [0x00 0x0a] "/sensors/1" # topic name + [0x14] # properties + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "1" # user property value + [0x26] # user property id + [0x00 0x04] "row2" # user property key + [0x00 0x01] "2" # user property value + "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/server.rpt new file mode 100644 index 0000000000..124f3bcb3e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.distinct/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x36] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x4a] # PUBLISH + [0x00 0x0a] "/sensors/1" # topic name + [0x14] # properties + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "1" # user property value + [0x26] # user property id + [0x00 0x04] "row2" # user property key + [0x00 0x01] "2" # user property value + "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/client.rpt new file mode 100644 index 0000000000..5a6125be45 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x36] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x4a] # PUBLISH + [0x00 0x0a] "/sensors/1" # topic name + [0x14] # properties + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "1" # user property value + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "2" # user property value + "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/server.rpt new file mode 100644 index 0000000000..4a7949c4b0 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.properties.repeated/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x36] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x4a] # PUBLISH + [0x00 0x0a] "/sensors/1" # topic name + [0x14] # properties + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "1" # user property value + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "2" # user property value + "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/client.rpt new file mode 100644 index 0000000000..ca65cc54cb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/client.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x36] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x3f] # PUBLISH + [0x00 0x0a] "/sensors/1" # topic name + [0x09] # properties + [0x26] # user property id + [0x00 0x03] "row" # user property key + [0x00 0x01] "1" # user property value + "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/server.rpt new file mode 100644 index 0000000000..551f767e18 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/publish.with.user.property/server.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x36] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x24] "755452d5-e2ef-4113-b9c6-2f53de96fd76" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x3f] # PUBLISH + [0x00 0x0a] "/sensors/1" # topic name + [0x09] # properties + [0x26] # user property id + [0x00 0x03] "row" # user property key + [0x00 0x01] "1" # user property value + "{\"id\":\"1\",\"unit\":\"CELSIUS\",\"value\":\"189\"}" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/client.rpt new file mode 100644 index 0000000000..9d1e963299 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/client.rpt @@ -0,0 +1,85 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write abort +read aborted +read notify FIRST_ABORTED + + +connect await FIRST_ABORTED + "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = non clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + + +read [0x20 0x08] # CONNACK + [0x01] # flags = session present + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/server.rpt new file mode 100644 index 0000000000..671fd9e422 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.abort.reconnect.non.clean.start/server.rpt @@ -0,0 +1,79 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read aborted +write abort + + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = non clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x01] # flags = session present + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/client.rpt new file mode 100644 index 0000000000..ff89e2d340 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/client.rpt @@ -0,0 +1,88 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write notify FIRST_CONNECTED + +read [0xe0 0x02] # DISCONNECT + [0x8e] # session taken over + [0x00] # properties = none + +read closed +write close + +connect await FIRST_CONNECTED + "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = non clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x01] # flags = session present + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/server.rpt new file mode 100644 index 0000000000..4b9121fce1 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.client.takeover/server.rpt @@ -0,0 +1,82 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xe0 0x02] # DISCONNECT + [0x8e] # session taken over + [0x00] # properties = none + +write close +read closed + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = non clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x01] # flags = session present + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.override.session.expiry/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.override.session.expiry/client.rpt new file mode 100644 index 0000000000..8df72dba57 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.override.session.expiry/client.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x15] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = none + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x11] 100 # session expiry interval + [0x00 0x08] "client-1" # client id + +read [0x20 0x0d] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x0a] # properties + [0x27] 66560 # maximum packet size + [0x11] 30 # session expiry interval + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.override.session.expiry/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.override.session.expiry/server.rpt new file mode 100644 index 0000000000..1d4c90db61 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.override.session.expiry/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x15] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = none + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x11] 100 # session expiry interval + [0x00 0x08] "client-1" # client id + +write [0x20 0x0d] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x0a] # properties + [0x27] 66560 # maximum packet size + [0x11] 30 # session expiry interval diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.payload.fragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.payload.fragmented/client.rpt new file mode 100644 index 0000000000..d713df5127 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.payload.fragmented/client.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x3a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x26] # flags = will retain, will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x00] # properties + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic +write [0x00 0x1a] "client one session expired" # will payload + +read [0x20 0x0c] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x09] # properties = none + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + [0x2a 0x00] # shared subscription unavailable diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.payload.fragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.payload.fragmented/server.rpt new file mode 100644 index 0000000000..7bc048cf43 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.payload.fragmented/server.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x3a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x26] # flags = will retain, will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x00] # properties + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +write [0x20 0x0c] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x09] # properties = none + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + [0x2a 0x00] # shared subscription unavailable diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/client.rpt new file mode 100644 index 0000000000..6027302d83 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/client.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x15] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = none + [0x00 0x3c] # keep alive = 60s + [0x0a] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x11] 1 # session expiry interval + [0x00 0x03] "one" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/server.rpt new file mode 100644 index 0000000000..077b01aa1f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.connect.with.session.expiry/server.rpt @@ -0,0 +1,39 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x15] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x00] # flags = none + [0x00 0x3c] # keep alive = 60s + [0x0a] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x11] 1 # session expiry interval + [0x00 0x03] "one" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/client.rpt new file mode 100644 index 0000000000..79ceb4828d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/client.rpt @@ -0,0 +1,82 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write notify FIRST_CONNECTED + +read [0xe0 0x02] # DISCONNECT + [0x8e] # session taken over + [0x00] # properties = none + +read closed +write close + + +connect await FIRST_CONNECTED + "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/server.rpt new file mode 100644 index 0000000000..779f119916 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.exists.clean.start/server.rpt @@ -0,0 +1,76 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xe0 0x02] # DISCONNECT + [0x8e] # session taken over + [0x00] # properties = none + +write close +read closed + + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.after.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.after.connack/client.rpt new file mode 100644 index 0000000000..6cd3a79255 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.after.connack/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x1c] # DISCONNECT + [0x9d] # reason code = Use another server + [0x1a] # properties + [0x1c 0x00 0x17] "mqtt-2.example.com:1883" # server reference + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.after.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.after.connack/server.rpt new file mode 100644 index 0000000000..1f9a0576de --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.after.connack/server.rpt @@ -0,0 +1,42 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x1c] # DISCONNECT + [0x9d] # reason code = Use another server + [0x1a] # properties + [0x1c 0x00 0x17] "mqtt-2.example.com:1883" # server reference diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.before.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.before.connack/client.rpt new file mode 100644 index 0000000000..ecb87b2a9c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.before.connack/client.rpt @@ -0,0 +1,36 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x1d] # CONNACK + [0x00] # flags = none + [0x9d] # reason code = Use another server + [0x1a] # properties + [0x1c 0x00 0x17] "mqtt-2.example.com:1883" # server reference diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.before.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.before.connack/server.rpt new file mode 100644 index 0000000000..804087d118 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.server.redirect.before.connack/server.rpt @@ -0,0 +1,37 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x1d] # CONNACK + [0x00] # flags = none + [0x9d] # reason code = Use another server + [0x1a] # properties + [0x1c 0x00 0x17] "mqtt-2.example.com:1883" # server reference diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.multiple.isolated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.multiple.isolated/client.rpt new file mode 100644 index 0000000000..5947d235ff --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.multiple.isolated/client.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.multiple.isolated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.multiple.isolated/server.rpt new file mode 100644 index 0000000000..a81ad21637 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.multiple.isolated/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.publish.routing/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.publish.routing/client.rpt new file mode 100644 index 0000000000..a925e86251 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.publish.routing/client.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x0d] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x05] "reply" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x16] # PUBLISH + [0x00 0x0b] "command/one" # topic name + [0x00] # properties + "message1" # payload + +write [0x30 0x16] # PUBLISH + [0x00 0x0b] "command/two" # topic name + [0x00] # properties + "message2" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.publish.routing/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.publish.routing/server.rpt new file mode 100644 index 0000000000..a430d57395 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.publish.routing/server.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x0d] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x05] "reply" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x16] # PUBLISH + [0x00 0x0b] "command/one" # topic name + [0x00] # properties + "message1" # payload + +read [0x30 0x16] # PUBLISH + [0x00 0x0b] "command/two" # topic name + [0x00] # properties + "message2" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/client.rpt new file mode 100644 index 0000000000..f32db6815a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/server.rpt new file mode 100644 index 0000000000..70e3bc9006 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe.via.session.state/server.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/client.rpt new file mode 100644 index 0000000000..3d57769f39 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/server.rpt new file mode 100644 index 0000000000..aa396a2aa4 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.subscribe/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/client.rpt new file mode 100644 index 0000000000..7da1547868 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/client.rpt @@ -0,0 +1,74 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +write [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x03] # packet id = 3 + [0x00] # properties = none + [0x00 0x0a] "sensor/two" # topic filter + +write notify UNSUBSCRIBE_ALL_FILTERS + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason code + +read [0xb0 0x04] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # unsubscribe = success + +read [0xb0 0x04] # UNSUBACK + [0x00 0x03] # packet id = 3 + [0x00] # properties = none + [0x00] # unsubscribe = success + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/server.rpt new file mode 100644 index 0000000000..908b65016f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe.deferred/server.rpt @@ -0,0 +1,73 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +read [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x03] # packet id = 3 + [0x00] # properties = none + [0x00 0x0a] "sensor/two" # topic filter + + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason code + +write [0xb0 0x04] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # unsubscribe = success + +write [0xb0 0x04] # UNSUBACK + [0x00 0x03] # packet id = 3 + [0x00] # properties = none + [0x00] # unsubscribe = success diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/client.rpt new file mode 100644 index 0000000000..95cb388d90 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x01] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +read [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 2 + [0x00] # properties = none + [0x00] # unsubscribe = success diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/server.rpt new file mode 100644 index 0000000000..5138218a62 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.unsubscribe.after.subscribe/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x01] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +write [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 2 + [0x00] # properties = none + [0x00] # unsubscribe = success diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/client.rpt new file mode 100644 index 0000000000..562889475f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x3f] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x02] # DISCONNECT + [0x04] # disconnect with will message + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/server.rpt new file mode 100644 index 0000000000..f3c7b6c9e9 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.disconnect.with.will.message/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x3f] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x02] # DISCONNECT + [0x04] # disconnect with will message + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/client.rpt new file mode 100644 index 0000000000..cb4483c26d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x3a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x02] # DISCONNECT + [0x8d] # reason = keep alive timeout + [0x00] # properties = none + +read closed +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/server.rpt new file mode 100644 index 0000000000..eeea697dfb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.no.ping.within.keep.alive/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x3a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x01] # keep alive = 1s + [0x00] # properties + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x02] # DISCONNECT + [0x8d] # reason = keep alive timeout + [0x00] # properties = none + +write close +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/client.rpt new file mode 100644 index 0000000000..35e3a75b84 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x3f] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0xe0 0x02] # DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/server.rpt new file mode 100644 index 0000000000..ed764ec0ef --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.normal.disconnect/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x3f] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x06] # flags = will flag, clean start + [0x00 0x0a] # keep alive = 10s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0xe0 0x02] # DISCONNECT + [0x00] # normal disconnect + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/client.rpt new file mode 100644 index 0000000000..1dd62ebb20 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/client.rpt @@ -0,0 +1,43 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x3f] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x26] # flags = will retain, will flag, clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +read [0x20 0x0c] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x09] # properties = none + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + [0x2a 0x00] # shared subscription unavailable diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/server.rpt new file mode 100644 index 0000000000..b3acd9ab04 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/session.will.message.retain/server.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x3f] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x26] # flags = will retain, will flag, clean start + [0x00 0x3c] # keep alive = 10s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x03] "one" # client id + [0x02] # will properties + [0x01 0x01] # format = utf-8 + [0x00 0x09] "wills/one" # will topic + [0x00 0x1a] "client one session expired" # will payload + +write [0x20 0x0c] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x09] # properties = none + [0x27] 66560 # maximum packet size = 66560 + [0x24 0x00] # maximum qos = at most once + [0x2a 0x00] # shared subscription unavailable diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/client.rpt new file mode 100644 index 0000000000..277b69e0bd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/server.rpt new file mode 100644 index 0000000000..b0ee5d909d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.get.retained.as.published/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/client.rpt new file mode 100644 index 0000000000..a2a9df28f2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x83 0x12] # malformed SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +read [0xe0 0x02] # disconnect = normal + [0x81] # malformed packet + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/server.rpt new file mode 100644 index 0000000000..f05e044a79 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.fixed.header.flags/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x83 0x12] # malformed SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +write [0xe0 0x02] # disconnect = normal + [0x81] # malformed packet + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/client.rpt new file mode 100644 index 0000000000..b89bfcd670 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0c] "#/sensor/one" # invalid topic filter + [0x00] # options = at-most-once, send retained + +read [0xe0 0x02] # disconnect = normal + [0x82] # protocol error + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/server.rpt new file mode 100644 index 0000000000..4938651215 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.invalid.topic.filter/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0c] "#/sensor/one" # invalid topic filter + [0x00] # options = at-most-once, send retained + +write [0xe0 0x02] # disconnect = normal + [0x82] # protocol error + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.missing.id.receive.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.missing.id.receive.message/client.rpt new file mode 100644 index 0000000000..4ed82006f8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.missing.id.receive.message/client.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.missing.id.receive.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.missing.id.receive.message/server.rpt new file mode 100644 index 0000000000..6f569a549b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.missing.id.receive.message/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt new file mode 100644 index 0000000000..23aa9e6031 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x3b] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x27] # properties + [0x0b 0x01] # subscription id = 1 + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt new file mode 100644 index 0000000000..fdef560e9b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x3b] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x27] # properties + [0x0b 0x01] # subscription id = 1 + [0x02] 0x0f # expiry = 15 seconds + [0x03 0x00 0x07] "message" # content type + [0x01 0x01] # format = utf-8 + [0x08 0x00 0x0a] "sensor/one" # response topic + [0x09 0x00 0x04] "info" # correlation data + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/client.rpt new file mode 100644 index 0000000000..ecdeb9a31f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/client.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x2c] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x18] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "1" # user property value + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "2" # user property value + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/server.rpt new file mode 100644 index 0000000000..c47f9ac934 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.user.properties.unaltered/server.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x2c] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x18] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "1" # user property value + [0x26] # user property id + [0x00 0x04] "row1" # user property key + [0x00 0x01] "2" # user property value + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/client.rpt new file mode 100644 index 0000000000..e1491aafbc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x00] # invalid subscriptionId = 0 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0xe0 0x02] # DISCONNECT = normal + [0x82] # protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/server.rpt new file mode 100644 index 0000000000..118e92c629 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message.with.invalid.subscription.id/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x00] # invalid subscriptionId = 0 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0xe0 0x02] # DISCONNECT = normal + [0x82] # protocol error + [0x00] # properties = none + +write close # close network connection diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/client.rpt new file mode 100644 index 0000000000..b337452ffd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/server.rpt new file mode 100644 index 0000000000..2fc37a55f7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.one.message/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/client.rpt new file mode 100644 index 0000000000..05c02a18c3 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/client.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x24] # options = at-most-once, no-local + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +read [0x30 0x19] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message2" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/server.rpt new file mode 100644 index 0000000000..a51e094552 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.publish.no.local/server.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x24] # options = at-most-once, no-local + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +write [0x30 0x19] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message2" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/client.rpt new file mode 100644 index 0000000000..3f96479fd4 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/client.rpt @@ -0,0 +1,80 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x1a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x08] "client-1" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x31 0x16] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +write notify PUBLISHED + +connect await PUBLISHED + "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x1a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x08] "client-2" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once, do not send retained + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/server.rpt new file mode 100644 index 0000000000..577e3c02eb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.publish.retained.no.replay/server.rpt @@ -0,0 +1,76 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x1a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x08] "client-1" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x31 0x16] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + + + +accepted +connected + +read [0x10 0x1a] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x08] "client-2" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once, do not send retained + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/client.rpt new file mode 100644 index 0000000000..409f0fe373 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/client.rpt @@ -0,0 +1,88 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x19] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x07] "client1" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x31 0x16] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +write notify RETAINED_PUBLISHED + + +connect await RETAINED_PUBLISHED + "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x19] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x07] "client2" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/server.rpt new file mode 100644 index 0000000000..421ddb838e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.qos0.replay.retained.no.packet.id/server.rpt @@ -0,0 +1,81 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x19] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x07] "client1" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x31 0x16] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +accepted +connected + +read [0x10 0x19] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x07] "client2" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/client.rpt new file mode 100644 index 0000000000..0bca00b003 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/client.rpt @@ -0,0 +1,69 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/+/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x0a] "sensor/+/1" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x1c] # PUBLISH + [0x00 0x0c] "sensor/one/1" # topic name + [0x06] # properties + [0x0b 0x01] # subscription id = 1 + [0x0b 0x02] # subscription id = 2 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/server.rpt new file mode 100644 index 0000000000..154bbbe696 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.overlapping.wildcard/server.rpt @@ -0,0 +1,70 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/+/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x0a] "sensor/+/1" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x1c] # PUBLISH + [0x00 0x0c] "sensor/one/1" # topic name + [0x06] # properties + [0x0b 0x01] # subscription id = 1 + [0x0b 0x02] # subscription id = 2 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/client.rpt new file mode 100644 index 0000000000..f4dc20f166 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/+" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/server.rpt new file mode 100644 index 0000000000..3ffcde5079 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message.wildcard/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/+" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/client.rpt new file mode 100644 index 0000000000..783b486b3f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/client.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/server.rpt new file mode 100644 index 0000000000..5a565e96fb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.message/server.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x16] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x02] # properties + [0x01 0x01] # format = utf-8 + "message" # payload + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.messages.topic.alias.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.messages.topic.alias.repeated/client.rpt new file mode 100644 index 0000000000..b8c281be48 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.messages.topic.alias.repeated/client.rpt @@ -0,0 +1,65 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x1b] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x07] # properties + [0x23 0x00 0x01] # topic alias = 1 + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload + +read [0x30 0x12] # PUBLISH + [0x00 0x00] # topic name + [0x07] # properties + [0x23 0x00 0x01] # topic alias = 1 + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message2" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.messages.topic.alias.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.messages.topic.alias.repeated/server.rpt new file mode 100644 index 0000000000..4c53a33405 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.receive.messages.topic.alias.repeated/server.rpt @@ -0,0 +1,66 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x1b] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x07] # properties + [0x23 0x00 0x01] # topic alias = 1 + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload + +write [0x30 0x12] # PUBLISH + [0x00 0x00] # topic name + [0x07] # properties + [0x23 0x00 0x01] # topic alias = 1 + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message2" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reconnect.publish.no.subscription/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reconnect.publish.no.subscription/client.rpt new file mode 100644 index 0000000000..b337452ffd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reconnect.publish.no.subscription/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reconnect.publish.no.subscription/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reconnect.publish.no.subscription/server.rpt new file mode 100644 index 0000000000..afc507ccc7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reconnect.publish.no.subscription/server.rpt @@ -0,0 +1,64 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload + +write [0x30 0x18] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x04] # properties + [0x0b 0x02] # subscription id = 2 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/client.rpt new file mode 100644 index 0000000000..f935b83e27 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x07] # options = malformed + +read [0xe0 0x02] # DISCONNECT + [0x81] # malformed packet + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/server.rpt new file mode 100644 index 0000000000..f915d88261 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.malformed.subscription.options/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x07] # options = malformed + +write [0xe0 0x02] # DISCONNECT + [0x81] # malformed packet + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/client.rpt new file mode 100644 index 0000000000..e8d88fb786 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x10] # SUBSCRIBE + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/server.rpt new file mode 100644 index 0000000000..4fe6b91fc7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.packet.id/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x10] # SUBSCRIBE + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/client.rpt new file mode 100644 index 0000000000..02d4452a51 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/client.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x03] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + +read [0xe0 0x02] # DISCONNECT + [0x00] # properties = none + [0x82] # reason = protocol error + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/server.rpt new file mode 100644 index 0000000000..efa46acd52 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.missing.topic.filters/server.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x03] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + +write [0xe0 0x02] # SUBACK + [0x00] # properties = none + [0x82] # reason code + +write close # close network connection diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/client.rpt new file mode 100644 index 0000000000..b981a2ef53 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/client.rpt @@ -0,0 +1,47 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x04] # options = at-most-once, send retained, no local + +read [0xe0 0x02] # DISCONNECT + [0x82] # protocol error + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/server.rpt new file mode 100644 index 0000000000..cae75dc440 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.no.local/server.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x04] # options = at-most-once, send retained, no local + +write [0xe0 0x02] # DISCONNECT + [0x82] # protocol error + [0x00] # properties = none diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/client.rpt new file mode 100644 index 0000000000..e74f580404 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x2a 0x00] # shared subscription unavailable + +write [0x82 0x23] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "$share/consumer1/sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +read [0xe0 0x02] # DISCONNECT + [0x9e] # shared subscription unavailable + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/server.rpt new file mode 100644 index 0000000000..955a0daa5a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.shared.subscriptions.not.supported/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x2a 0x00] # shared subscription unavailable + +read [0x82 0x23] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "$share/consumer1/sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +write [0xe0 0x02] # DISCONNECT + [0x9e] # shared subscription unavailable + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/client.rpt new file mode 100644 index 0000000000..b4ab99c3ab --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x29 0x00] # subscription identifiers unavailable + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +read [0xe0 0x02] # DISCONNECT + [0xa1] # subscription identifiers unavailable + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/server.rpt new file mode 100644 index 0000000000..68c5d5f498 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.subscription.ids.not.supported/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x29 0x00] # subscription identifiers unavailable + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x00] # options = at-most-once, send retained + +write [0xe0 0x02] # DISCONNECT + [0xa1] # subscription identifiers unavailable + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/client.rpt new file mode 100644 index 0000000000..85b8c1d71d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/client.rpt @@ -0,0 +1,48 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#/1" # topic filter + [0x00] # options = at-most-once, send retained + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x8f] # reason code = topic filter invalid diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/server.rpt new file mode 100644 index 0000000000..7d38220bd3 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.topic.filter.invalid.wildcard/server.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#/1" # topic filter + [0x00] # options = at-most-once, send retained + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x8f] # reason code = topic filter invalid diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt new file mode 100644 index 0000000000..4c01193032 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x28 0x00] # wildcard subscription unavailable + +write [0x82 0x14] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0c] "sensor/one/#" # topic filter + [0x00] # options = at-most-once, send retained + +read [0xe0 0x02] # DISCONNECT + [0xa2] # wildcard subscription unavailable + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt new file mode 100644 index 0000000000..3a5baf1ab2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt @@ -0,0 +1,51 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x0a] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x07] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x28 0x00] # wildcard subscription unavailable + +read [0x82 0x14] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0c] "sensor/one/#" # topic filter + [0x00] # options = at-most-once, send retained + +write [0xe0 0x02] # DISCONNECT + [0xa2] # wildcard subscription unavailable + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/client.rpt new file mode 100644 index 0000000000..453f097b77 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/client.rpt @@ -0,0 +1,56 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x08] # options = at-most-once, retain as published + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x31 0x18] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/server.rpt new file mode 100644 index 0000000000..6d00c8560d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.retain.as.published/server.rpt @@ -0,0 +1,57 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x08] # options = at-most-once, retain as published + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x31 0x18] # PUBLISH flags = at-most-once, retain + [0x00 0x0a] "sensor/one" # topic name + [0x04] # properties + [0x0b 0x01] # subscription id = 1 + [0x01 0x01] # format = utf-8 + "message" # payload \ No newline at end of file diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/client.rpt new file mode 100644 index 0000000000..227e0beb21 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/server.rpt new file mode 100644 index 0000000000..c597263fca --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.multi.level.wildcard/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt new file mode 100644 index 0000000000..c99c84404f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x14] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0c] "sensor/+/1/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt new file mode 100644 index 0000000000..6ddf6646ee --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x14] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0c] "sensor/+/1/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/client.rpt new file mode 100644 index 0000000000..3d57769f39 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/server.rpt new file mode 100644 index 0000000000..d02df55929 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.exact/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/client.rpt new file mode 100644 index 0000000000..b485f291fb --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/+" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/server.rpt new file mode 100644 index 0000000000..9c5b520f69 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.single.level.wildcard/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/+" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/client.rpt new file mode 100644 index 0000000000..d2233d81cf --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/client.rpt @@ -0,0 +1,49 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/+/+" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/server.rpt new file mode 100644 index 0000000000..d34fd3f718 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filter.two.single.level.wildcard/server.rpt @@ -0,0 +1,50 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/+/+" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/client.rpt new file mode 100644 index 0000000000..2f9d51154f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/server.rpt new file mode 100644 index 0000000000..71cdb546db --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.both.exact/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt new file mode 100644 index 0000000000..2c383704f5 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1d] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt new file mode 100644 index 0000000000..f08abd750d --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1d] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/client.rpt new file mode 100644 index 0000000000..c4ce6f4248 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1b] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#" # topic filter + [0x20] # options = at-most-once + + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/server.rpt new file mode 100644 index 0000000000..77fc3304c7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.disjoint.wildcards/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1b] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#" # topic filter + [0x20] # options = at-most-once + + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact.no.subscription.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact.no.subscription.id/client.rpt new file mode 100644 index 0000000000..6c387a6a09 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact.no.subscription.id/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact.no.subscription.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact.no.subscription.id/server.rpt new file mode 100644 index 0000000000..e823ccd680 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact.no.subscription.id/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/client.rpt new file mode 100644 index 0000000000..d89bb05a76 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/client.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/server.rpt new file mode 100644 index 0000000000..77a0e0c46b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.exact/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/client.rpt new file mode 100644 index 0000000000..465075bc5a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/client.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/server.rpt new file mode 100644 index 0000000000..2612d5d1e7 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.both.wildcard/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x08] "sensor/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt new file mode 100644 index 0000000000..b58790c323 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0x82 0x10] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt new file mode 100644 index 0000000000..1021208d2a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0x82 0x10] # SUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x02] # properties + [0x0b 0x02] # subscription id = 2 + [0x00 0x08] "device/#" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.non.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.non.successful/client.rpt new file mode 100644 index 0000000000..5a3336f50e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.non.successful/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x87] # reason codes = Success, Not authorized diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.non.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.non.successful/server.rpt new file mode 100644 index 0000000000..b64c8365cd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.non.successful/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x87] # reason codes = Success, Not authorized diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/client.rpt new file mode 100644 index 0000000000..b0a40a4e2b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/client.rpt @@ -0,0 +1,52 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/+/#" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/+/1" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/server.rpt new file mode 100644 index 0000000000..f5c636679b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/subscribe.topic.filters.overlapping.wildcards/server.rpt @@ -0,0 +1,53 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/+/#" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/+/1" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/client.rpt new file mode 100644 index 0000000000..23a116d772 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +read [0xb0 0x04] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # unsubscribe = success diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/server.rpt new file mode 100644 index 0000000000..fafc1898d8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.after.subscribe/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +write [0xb0 0x04] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # unsubscribe = success diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/client.rpt new file mode 100644 index 0000000000..a5218b69f3 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/client.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason code + +write [0xa2 0x1b] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + [0x00 0x0a] "sensor/two" # topic filter + +read [0xb0 0x05] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/server.rpt new file mode 100644 index 0000000000..5469d03e35 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.aggregated.topic.filters.both.exact/server.rpt @@ -0,0 +1,65 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes + + +read [0xa2 0x1b] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + [0x00 0x0a] "sensor/two" # topic filter + +write [0xb0 0x05] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/client.rpt new file mode 100644 index 0000000000..21707596c8 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/client.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xa2 0x11] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0c] "not-matching" # topic filter + +read [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x11] # unsubscribe = no subscription existed + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/server.rpt new file mode 100644 index 0000000000..91fe86981e --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.subscription/server.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0xa2 0x11] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0c] "not-matching" # topic filter + +write [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x11] # unsubscribe = no subscription existed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/client.rpt new file mode 100644 index 0000000000..1a15fe66bd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0a] "not-matching" # topic filter + +read [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x11] # unsubscribe = no subscription existed + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/server.rpt new file mode 100644 index 0000000000..b99ca469e1 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.no.matching.topic.filter/server.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0a] "not-matching" # topic filter + +write [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x11] # unsubscribe = no subscription existed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/client.rpt new file mode 100644 index 0000000000..e3fc8f7e1b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/client.rpt @@ -0,0 +1,65 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason code + +write [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + [0x30 0x14] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x00] # properties + "message" # payload + +read [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/server.rpt new file mode 100644 index 0000000000..5eeb52dd97 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.publish.unfragmented/server.rpt @@ -0,0 +1,67 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes + + +read [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + [0x30 0x14] # PUBLISH + [0x00 0x0a] "sensor/two" # topic name + [0x00] # properties + "message" # payload + +write [0xb0 0x04] # UNSUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/client.rpt new file mode 100644 index 0000000000..9788f07ecd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/client.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xa3 0x0f] # malformed UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +read [0xe0 0x02] # disconnect = normal + [0x81] # malformed packet + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/server.rpt new file mode 100644 index 0000000000..25a951ba8b --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.invalid.fixed.header.flags/server.rpt @@ -0,0 +1,60 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0xa3 0x0f] # malformed UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +write [0xe0 0x02] # disconnect = normal + [0x81] # malformed packet + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/client.rpt new file mode 100644 index 0000000000..af9631abd1 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/client.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xa2 0x0d] # UNSUBSCRIBE + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +read [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/server.rpt new file mode 100644 index 0000000000..a381e9a905 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.missing.packet.id/server.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0xa2 0x0d] # UNSUBSCRIBE + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +write [0xe0 0x02] # disconnect header + [0x82] # disconnect = protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/client.rpt new file mode 100644 index 0000000000..1a0c4e388c --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/client.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +write [0xa2 0x03] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + +read [0xe0 0x02] # DISCONNECT + [0x82] # protocol error + [0x00] # properties = none + +read closed diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/server.rpt new file mode 100644 index 0000000000..6c370e90cd --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.reject.no.topic.filter/server.rpt @@ -0,0 +1,59 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x13] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3C] # keep alive = 60s + [0x00] # properties = none + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x12] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x04] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00] # reason code + +read [0xa2 0x03] # UNSUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + +write [0xe0 0x02] # DISCONNECT + [0x82] # protocol error + [0x00] # properties = none + +write close diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/client.rpt new file mode 100644 index 0000000000..501c328d13 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/client.rpt @@ -0,0 +1,62 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason code + +write [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +read [0xb0 0x04] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/server.rpt new file mode 100644 index 0000000000..8ad80ca804 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filter.single/server.rpt @@ -0,0 +1,64 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes + + +read [0xa2 0x0f] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + +write [0xb0 0x04] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00] # reason codes diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filters.non.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filters.non.successful/client.rpt new file mode 100644 index 0000000000..fdbbb144bc --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filters.non.successful/client.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + +write [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +read [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason code + +write [0xa2 0x1b] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + [0x00 0x0a] "sensor/two" # topic filter + +read [0xb0 0x05] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x87] # reason codes = Success, Not authorized diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filters.non.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filters.non.successful/server.rpt new file mode 100644 index 0000000000..b8ddf0d53a --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/unsubscribe.topic.filters.non.successful/server.rpt @@ -0,0 +1,65 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x08] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x05] # properties = none + [0x27] 66560 # maximum packet size = 66560 + +read [0x82 0x1f] # SUBSCRIBE + [0x00 0x01] # packet id = 1 + [0x02] # properties + [0x0b 0x01] # subscription id = 1 + [0x00 0x0a] "sensor/one" # topic filter + [0x20] # options = at-most-once + + [0x00 0x0a] "sensor/two" # topic filter + [0x20] # options = at-most-once + +write [0x90 0x05] # SUBACK + [0x00 0x01] # packet id = 1 + [0x00] # properties = none + [0x00 0x00] # reason codes + + +read [0xa2 0x1b] # UNSUBSCRIBE + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x0a] "sensor/one" # topic filter + [0x00 0x0a] "sensor/two" # topic filter + +write [0xb0 0x05] # UNSUBACK + [0x00 0x02] # packet id = 2 + [0x00] # properties = none + [0x00 0x87] # reason codes = Success, Not authorized diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/config/SchemaTest.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/config/SchemaTest.java new file mode 100644 index 0000000000..c1d97f1a32 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/config/SchemaTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.config; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; + +import jakarta.json.JsonObject; + +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; + +import io.aklivity.zilla.specs.engine.config.ConfigSchemaRule; + +public class SchemaTest +{ + @Rule + public final ConfigSchemaRule schema = new ConfigSchemaRule() + .schemaPatch("io/aklivity/zilla/specs/binding/mqtt/schema/mqtt.schema.patch.json") + .schemaPatch("io/aklivity/zilla/specs/engine/schema/guard/test.schema.patch.json") + .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/config"); + + @Ignore("TODO") + @Test + public void shouldValidateClient() + { + JsonObject config = schema.validate("client.yaml"); + + assertThat(config, not(nullValue())); + } + + @Ignore("TODO") + @Test + public void shouldValidateClientWhenTopic() + { + JsonObject config = schema.validate("client.when.topic.yaml"); + + assertThat(config, not(nullValue())); + } + + @Ignore("TODO") + @Test + public void shouldValidateClientWhenTopicOrSessions() + { + JsonObject config = schema.validate("client.when.topic.or.sessions.yaml"); + + assertThat(config, not(nullValue())); + } + + @Ignore("TODO") + @Test + public void shouldValidateClientWhenTopicPublishOnly() + { + JsonObject config = schema.validate("client.when.topic.publish.only.yaml"); + + assertThat(config, not(nullValue())); + } + + @Ignore("TODO") + @Test + public void shouldValidateClientWhenTopicSubscribeOnly() + { + JsonObject config = schema.validate("client.when.topic.subscribe.only.yaml"); + + assertThat(config, not(nullValue())); + } + + @Test + public void shouldValidateServer() + { + JsonObject config = schema.validate("server.yaml"); + + assertThat(config, not(nullValue())); + } + + @Test + public void shouldValidateServerWithAuthorizationOptions() + { + JsonObject config = schema.validate("server.credentials.username.yaml"); + + assertThat(config, not(nullValue())); + } + + @Test + public void shouldValidateServerWhenRouteToNonDefault() + { + JsonObject config = schema.validate("server.route.non.default.yaml"); + + assertThat(config, not(nullValue())); + } +} diff --git a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java similarity index 82% rename from incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java rename to specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java index ea3eca34a1..2b2b12b726 100644 --- a/incubator/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java @@ -29,13 +29,15 @@ import org.junit.Test; import org.kaazing.k3po.lang.el.BytesMatcher; -import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttEndReasonCode; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttPayloadFormat; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSessionSignalFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSessionSignalType; import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttSessionStateFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.MqttWillMessageFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttDataExFW; -import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttEndExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttFlushExFW; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttResetExFW; public class MqttFunctionsTest { @@ -60,19 +62,12 @@ public void shouldEncodeMqttSessionBeginExt() final byte[] array = MqttFunctions.beginEx() .typeId(0) .session() - .clientId("client") + .flags("WILL", "CLEAN_START") .expiry(30) - .will() - .topic("will.client") - .delay(20) - .expiryInterval(15) - .contentType("message") - .format("TEXT") - .responseTopic("will.client.response") - .correlation("request-id-1") - .userProperty("name", "value") - .payload("client failed") - .build() + .qosMax(1) + .packetSizeMax(100) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") .build() .build(); @@ -82,20 +77,10 @@ public void shouldEncodeMqttSessionBeginExt() assertEquals(2, mqttBeginEx.kind()); assertEquals("client", mqttBeginEx.session().clientId().asString()); assertEquals(30, mqttBeginEx.session().expiry()); - assertEquals("will.client", mqttBeginEx.session().will().topic().asString()); - assertEquals(20, mqttBeginEx.session().will().delay()); - assertEquals(15, mqttBeginEx.session().will().expiryInterval()); - assertEquals("message", mqttBeginEx.session().will().contentType().asString()); - assertEquals("TEXT", mqttBeginEx.session().will().format().toString()); - assertEquals("will.client.response", mqttBeginEx.session().will().responseTopic().asString()); - assertEquals("request-id-1", mqttBeginEx.session().will().correlation() - .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))); - assertNotNull(mqttBeginEx.session().will().properties() - .matchFirst(h -> - "name".equals(h.key().asString()) && - "value".equals(h.value().asString()))); - assertEquals("client failed", mqttBeginEx.session().will().payload() - .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))); + assertEquals(1, mqttBeginEx.session().qosMax()); + assertEquals(100, mqttBeginEx.session().packetSizeMax()); + assertEquals(7, mqttBeginEx.session().capabilities()); + assertEquals(6, mqttBeginEx.session().flags()); } @Test @@ -104,8 +89,8 @@ public void shouldEncodeMqttSessionBeginExtWithoutWillMessage() final byte[] array = MqttFunctions.beginEx() .typeId(0) .session() - .clientId("client") .expiry(30) + .clientId("client") .build() .build(); @@ -124,13 +109,6 @@ public void shouldEncodeMqttSessionBeginExtWithFlagsBytesWillPayload() .typeId(0) .session() .clientId("client") - .will() - .topic("will.client") - .qos("AT_LEAST_ONCE") - .flags("RETAIN") - .correlationBytes("request-id-1".getBytes(UTF_8)) - .payloadBytes(new byte[] {0, 1, 2, 3, 4, 5}) - .build() .build() .build(); @@ -139,14 +117,6 @@ public void shouldEncodeMqttSessionBeginExtWithFlagsBytesWillPayload() assertEquals(2, mqttBeginEx.kind()); assertEquals("client", mqttBeginEx.session().clientId().asString()); - assertEquals("will.client", mqttBeginEx.session().will().topic().asString()); - assertEquals(1, mqttBeginEx.session().will().flags()); - assertEquals(0b0001, mqttBeginEx.session().will().flags()); - assertEquals("BINARY", mqttBeginEx.session().will().format().toString()); - assertEquals("request-id-1", mqttBeginEx.session().will().correlation() - .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))); - assertArrayEquals(new byte[] {0, 1, 2, 3, 4, 5}, mqttBeginEx.session().will().payload() - .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)).getBytes()); } @Test @@ -219,6 +189,31 @@ public void shouldEncodeMqttSubscribeBeginExtWithFlags() 0b0001 == f.flags())); } + @Test + public void shouldMatchPublishBeginExtension() throws Exception + { + BytesMatcher matcher = MqttFunctions.matchBeginEx() + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() + .build(); + + ByteBuffer byteBuf = ByteBuffer.allocate(1024); + + new MqttBeginExFW.Builder() + .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) + .typeId(0x01) + .publish(f -> f + .clientId("client") + .topic("sensor/one") + .flags(1)) + .build(); + + assertNotNull(matcher.match(byteBuf)); + } + @Test public void shouldMatchSubscribeBeginExtension() throws Exception { @@ -259,7 +254,7 @@ public void shouldMatchSubscribeBeginExtensionDefaults() throws Exception .typeId(0x01) .subscribe(f -> f .clientId("client") - .filtersItem(p -> p.subscriptionId(1).qos(0).flags(1).pattern("sensor/one"))) + .filtersItem(p -> p.subscriptionId(1).qos(0).flags(0).pattern("sensor/one"))) .build(); assertNotNull(matcher.match(byteBuf)); @@ -282,7 +277,7 @@ public void shouldMatchSubscribeBeginExtensionNoSubscriptionId() throws Exceptio .typeId(0x01) .subscribe(f -> f .clientId("client") - .filtersItem(p -> p.qos(0).flags(1).pattern("sensor/one"))) + .filtersItem(p -> p.qos(0).flags(0).pattern("sensor/one"))) .build(); assertNotNull(matcher.match(byteBuf)); @@ -293,21 +288,12 @@ public void shouldMatchSessionBeginExtension() throws Exception { BytesMatcher matcher = MqttFunctions.matchBeginEx() .session() - .clientId("client") + .flags("CLEAN_START") .expiry(10) - .will() - .topic("willTopic") - .delay(10) - .qos("AT_MOST_ONCE") - .flags("RETAIN") - .expiryInterval(20) - .contentType("message") - .format("TEXT") - .responseTopic("willResponseTopic") - .correlation("correlationData") - .userProperty("key1", "value1") - .payload("will message") - .build() + .qosMax(1) + .packetSizeMax(100) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") .build() .build(); @@ -317,22 +303,12 @@ public void shouldMatchSessionBeginExtension() throws Exception .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x00) .session(s -> s - .clientId("client") + .flags(2) .expiry(10) - .will(c -> - { - c.topic("willTopic"); - c.delay(10); - c.qos(0); - c.flags(1); - c.expiryInterval(20); - c.contentType("message"); - c.format(f -> f.set(MqttPayloadFormat.TEXT)); - c.responseTopic("willResponseTopic"); - c.correlation(corr -> corr.bytes(b -> b.set("correlationData".getBytes(UTF_8)))); - c.propertiesItem(p -> p.key("key1").value("value1")); - c.payload(p -> p.bytes(b -> b.set("will message".getBytes(UTF_8)))); - })) + .qosMax(1) + .packetSizeMax(100) + .capabilities(7) + .clientId("client")) .build(); assertNotNull(matcher.match(byteBuf)); @@ -343,8 +319,8 @@ public void shouldMatchSessionBeginExtensionWithEmptyFields() throws Exception { BytesMatcher matcher = MqttFunctions.matchBeginEx() .session() - .clientId("client") .expiry(10) + .clientId("client") .build() .build(); @@ -354,8 +330,8 @@ public void shouldMatchSessionBeginExtensionWithEmptyFields() throws Exception .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x00) .session(s -> s - .clientId("client") - .expiry(10)) + .expiry(10) + .clientId("client")) .build(); assertNotNull(matcher.match(byteBuf)); @@ -366,20 +342,8 @@ public void shouldMatchSessionBeginExtensionWithBytes() throws Exception { BytesMatcher matcher = MqttFunctions.matchBeginEx() .session() - .clientId("client") .expiry(10) - .will() - .topic("willTopic") - .delay(10) - .qos("AT_MOST_ONCE") - .expiryInterval(20) - .contentType("message") - .format("TEXT") - .responseTopic("willResponseTopic") - .correlationBytes("correlationData".getBytes(UTF_8)) - .userProperty("key1", "value1") - .payloadBytes("will message".getBytes(UTF_8)) - .build() + .clientId("client") .build() .build(); @@ -389,35 +353,23 @@ public void shouldMatchSessionBeginExtensionWithBytes() throws Exception .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) .typeId(0x00) .session(s -> s - .clientId("client") .expiry(10) - .will(c -> - { - c.topic("willTopic"); - c.delay(10); - c.qos(0); - c.expiryInterval(20); - c.contentType("message"); - c.format(f -> f.set(MqttPayloadFormat.TEXT)); - c.responseTopic("willResponseTopic"); - c.correlation(corr -> corr.bytes(b -> b.set("correlationData".getBytes(UTF_8)))); - c.propertiesItem(p -> p.key("key1").value("value1")); - c.payload(p -> p.bytes(b -> b.set("will message".getBytes(UTF_8)))); - })) + .clientId("client")) .build(); assertNotNull(matcher.match(byteBuf)); } @Test - public void shouldEncodeMqttProduceBeginEx() + public void shouldEncodeMqttPublishBeginEx() { final byte[] array = MqttFunctions.beginEx() .typeId(0) .publish() - .clientId("client") - .topic("sensor/one") - .build() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .build() .build(); DirectBuffer buffer = new UnsafeBuffer(array); @@ -426,6 +378,7 @@ public void shouldEncodeMqttProduceBeginEx() assertEquals(0, mqttBeginEx.kind()); assertEquals("client", mqttBeginEx.publish().clientId().asString()); assertEquals("sensor/one", mqttBeginEx.publish().topic().asString()); + assertEquals(1, mqttBeginEx.publish().flags()); } @Test @@ -829,7 +782,6 @@ public void shouldMatchPublishDataExtension() throws Exception { BytesMatcher matcher = MqttFunctions.matchDataEx() .publish() - .topic("sensor/one") .qos("AT_MOST_ONCE") .flags("RETAIN") .expiryInterval(20) @@ -848,7 +800,6 @@ public void shouldMatchPublishDataExtension() throws Exception .typeId(0x00) .publish(p -> { - p.topic("sensor/one"); p.qos(0); p.flags(1); p.expiryInterval(20); @@ -868,7 +819,6 @@ public void shouldMatchPublishDataExtensionWithBytes() throws Exception { BytesMatcher matcher = MqttFunctions.matchDataEx() .publish() - .topic("sensor/one") .qos("AT_MOST_ONCE") .expiryInterval(20) .contentType("message") @@ -886,7 +836,6 @@ public void shouldMatchPublishDataExtensionWithBytes() throws Exception .typeId(0x00) .publish(p -> { - p.topic("sensor/one"); p.qos(0); p.expiryInterval(20); p.contentType("message"); @@ -905,7 +854,6 @@ public void shouldMatchPublishDataExtensionWithEmptyFields() throws Exception { BytesMatcher matcher = MqttFunctions.matchDataEx() .publish() - .topic("sensor/one") .qos("AT_MOST_ONCE") .build() .build(); @@ -917,7 +865,6 @@ public void shouldMatchPublishDataExtensionWithEmptyFields() throws Exception .typeId(0x00) .publish(p -> { - p.topic("sensor/one"); p.flags(0); }) .build(); @@ -931,7 +878,6 @@ public void shouldEncodeMqttPublishDataEx() final byte[] array = MqttFunctions.dataEx() .typeId(0) .publish() - .topic("sensor/one") .expiryInterval(15) .contentType("message") .format("TEXT") @@ -945,7 +891,6 @@ public void shouldEncodeMqttPublishDataEx() MqttDataExFW mqttPublishDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttPublishDataEx.typeId()); - assertEquals("sensor/one", mqttPublishDataEx.publish().topic().asString()); assertEquals(15, mqttPublishDataEx.publish().expiryInterval()); assertEquals("message", mqttPublishDataEx.publish().contentType().asString()); assertEquals("TEXT", mqttPublishDataEx.publish().format().toString()); @@ -964,7 +909,6 @@ public void shouldEncodeMqttPublishDataExWithUserProperty() final byte[] array = MqttFunctions.dataEx() .typeId(0) .publish() - .topic("sensor/one") .userProperty("name", "value") .build() .build(); @@ -973,7 +917,6 @@ public void shouldEncodeMqttPublishDataExWithUserProperty() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertEquals("sensor/one", mqttDataEx.publish().topic().asString()); assertNotNull(mqttDataEx.publish().properties() .matchFirst(h -> "name".equals(h.key().asString()) && @@ -986,7 +929,6 @@ public void shouldEncodeMqttPublishDataExWithFlags() final byte[] array = MqttFunctions.dataEx() .typeId(0) .publish() - .topic("sensor/one") .qos("EXACTLY_ONCE") .flags("RETAIN") .build() @@ -996,7 +938,6 @@ public void shouldEncodeMqttPublishDataExWithFlags() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertEquals("sensor/one", mqttDataEx.publish().topic().asString()); assertEquals(2, mqttDataEx.publish().qos()); assertEquals(0b0001, mqttDataEx.publish().flags()); } @@ -1027,7 +968,6 @@ public void shouldEncodeMqttPublishDataExWithUserProperties() final byte[] array = MqttFunctions.dataEx() .typeId(0) .publish() - .topic("sensor/one") .userProperty("name1", "value1") .userProperty("name2", "value2") .build() @@ -1037,7 +977,6 @@ public void shouldEncodeMqttPublishDataExWithUserProperties() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertEquals("sensor/one", mqttDataEx.publish().topic().asString()); assertNotNull(mqttDataEx.publish().properties() .matchFirst(h -> "name1".equals(h.key().asString()) && @@ -1067,7 +1006,6 @@ public void shouldEncodeMqttPublishDataExWithoutTopic() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertNull(mqttDataEx.publish().topic().asString()); assertEquals(15, mqttDataEx.publish().expiryInterval()); assertEquals("message", mqttDataEx.publish().contentType().asString()); assertEquals("TEXT", mqttDataEx.publish().format().toString()); @@ -1086,7 +1024,6 @@ public void shouldEncodeMqttPublishDataExWithoutResponseTopic() final byte[] array = MqttFunctions.dataEx() .typeId(0) .publish() - .topic("sensor/one") .expiryInterval(15) .contentType("message") .format("TEXT") @@ -1099,7 +1036,6 @@ public void shouldEncodeMqttPublishDataExWithoutResponseTopic() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertEquals("sensor/one", mqttDataEx.publish().topic().asString()); assertEquals(15, mqttDataEx.publish().expiryInterval()); assertEquals("message", mqttDataEx.publish().contentType().asString()); assertEquals("TEXT", mqttDataEx.publish().format().toString()); @@ -1129,7 +1065,6 @@ public void shouldEncodeMqttPublishDataExWithNullDefaults() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertNull(mqttDataEx.publish().topic().asString()); assertEquals(15, mqttDataEx.publish().expiryInterval()); assertNull(mqttDataEx.publish().contentType().asString()); assertEquals("TEXT", mqttDataEx.publish().format().toString()); @@ -1148,7 +1083,6 @@ public void shouldEncodeMqttPublishDataExWithBytes() final byte[] array = MqttFunctions.dataEx() .typeId(0) .publish() - .topic("sensor/one") .expiryInterval(15) .contentType("message") .format("TEXT") @@ -1162,7 +1096,6 @@ public void shouldEncodeMqttPublishDataExWithBytes() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertEquals("sensor/one", mqttDataEx.publish().topic().asString()); assertEquals(15, mqttDataEx.publish().expiryInterval()); assertEquals("message", mqttDataEx.publish().contentType().asString()); assertEquals("TEXT", mqttDataEx.publish().format().toString()); @@ -1181,7 +1114,6 @@ public void shouldEncodeMqttPublishDataExWithNullUserPropertyValue() final byte[] array = MqttFunctions.dataEx() .typeId(0) .publish() - .topic("sensor/one") .expiryInterval(15) .contentType("message") .format("TEXT") @@ -1195,7 +1127,6 @@ public void shouldEncodeMqttPublishDataExWithNullUserPropertyValue() MqttDataExFW mqttDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); assertEquals(0, mqttDataEx.typeId()); - assertEquals("sensor/one", mqttDataEx.publish().topic().asString()); assertEquals(15, mqttDataEx.publish().expiryInterval()); assertEquals("message", mqttDataEx.publish().contentType().asString()); assertEquals("TEXT", mqttDataEx.publish().format().toString()); @@ -1208,6 +1139,23 @@ public void shouldEncodeMqttPublishDataExWithNullUserPropertyValue() Objects.isNull(h.value().asString()))); } + @Test + public void shouldEncodeMqttSessionDataEx() + { + final byte[] array = MqttFunctions.dataEx() + .typeId(0) + .session() + .kind("WILL") + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttDataExFW mqttPublishDataEx = new MqttDataExFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(0, mqttPublishDataEx.typeId()); + assertEquals("WILL", mqttPublishDataEx.session().kind().toString()); + } + @Test public void shouldEncodeMqttSubscribeFlushEx() { @@ -1231,32 +1179,32 @@ public void shouldEncodeMqttSubscribeFlushEx() } @Test - public void shouldEncodeMqttAbortExAsUnsubscribe() + public void shouldEncodeMqttResetEx() { - final byte[] array = MqttFunctions.endEx() + final byte[] array = MqttFunctions.resetEx() .typeId(0) - .reason("KEEP_ALIVE_EXPIRY") + .serverRef("mqtt-1.example.com:1883") + .reasonCode(0) .build(); DirectBuffer buffer = new UnsafeBuffer(array); - MqttEndExFW mqttEndEx = new MqttEndExFW().wrap(buffer, 0, buffer.capacity()); - assertEquals(0, mqttEndEx.typeId()); - assertEquals(MqttEndReasonCode.KEEP_ALIVE_EXPIRY, mqttEndEx.reasonCode().get()); + MqttResetExFW mqttResetEx = new MqttResetExFW().wrap(buffer, 0, buffer.capacity()); + assertEquals(0, mqttResetEx.typeId()); + assertEquals("mqtt-1.example.com:1883", mqttResetEx.serverRef().asString()); + assertEquals(0, mqttResetEx.reasonCode()); } @Test public void shouldEncodeMqttSessionState() { final byte[] array = MqttFunctions.session() - .clientId("client") .subscription("sensor/one", 1, "AT_MOST_ONCE", "SEND_RETAINED") - .subscription("sensor/two") + .subscription("sensor/two", 1, 0) .build(); DirectBuffer buffer = new UnsafeBuffer(array); MqttSessionStateFW sessionState = new MqttSessionStateFW().wrap(buffer, 0, buffer.capacity()); - assertEquals("client", sessionState.clientId().asString()); assertNotNull(sessionState.subscriptions() .matchFirst(f -> "sensor/one".equals(f.pattern().asString()) && @@ -1267,7 +1215,167 @@ public void shouldEncodeMqttSessionState() assertNotNull(sessionState.subscriptions() .matchFirst(f -> "sensor/two".equals(f.pattern().asString()) && + 1 == f.subscriptionId() && 0 == f.qos() && - 0b0001 == f.flags())); + 0 == f.reasonCode() && + 0b0000 == f.flags())); + } + + @Test + public void shouldEncodeWillMessage() + { + final byte[] array = MqttFunctions.will() + .topic("will.client") + .delay(20) + .expiryInterval(15) + .contentType("message") + .format("TEXT") + .responseTopic("will.client.response") + .lifetimeId("1") + .willId("2") + .correlation("request-id-1") + .userProperty("name", "value") + .payload("client failed") + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttWillMessageFW willMessage = new MqttWillMessageFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals("will.client", willMessage.topic().asString()); + assertEquals(20, willMessage.delay()); + assertEquals(15, willMessage.expiryInterval()); + assertEquals("message", willMessage.contentType().asString()); + assertEquals("TEXT", willMessage.format().toString()); + assertEquals("will.client.response", willMessage.responseTopic().asString()); + assertEquals("1", willMessage.lifetimeId().asString()); + assertEquals("2", willMessage.willId().asString()); + assertEquals("request-id-1", willMessage.correlation() + .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))); + assertNotNull(willMessage.properties() + .matchFirst(h -> + "name".equals(h.key().asString()) && + "value".equals(h.value().asString()))); + assertEquals("client failed", willMessage.payload() + .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))); + } + + @Test + public void shouldEncodeWillMessageBytesPayload() + { + final byte[] array = MqttFunctions.will() + .topic("will.client") + .qos("AT_LEAST_ONCE") + .flags("RETAIN") + .responseTopic("response_topic") + .correlationBytes("request-id-1".getBytes(UTF_8)) + .payloadBytes(new byte[] {0, 1, 2, 3, 4, 5}) + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttWillMessageFW willMessage = new MqttWillMessageFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals("will.client", willMessage.topic().asString()); + assertEquals(1, willMessage.flags()); + assertEquals(0b0001, willMessage.flags()); + assertEquals("NONE", willMessage.format().toString()); + assertEquals("response_topic", willMessage.responseTopic().asString()); + assertEquals("request-id-1", willMessage.correlation() + .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o))); + assertArrayEquals(new byte[] {0, 1, 2, 3, 4, 5}, willMessage.payload() + .bytes().get((b, o, m) -> b.getStringWithoutLengthUtf8(o, m - o)).getBytes()); + } + + @Test + public void shouldEncodeWillSignal() + { + final byte[] array = MqttFunctions.sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(20) + .deliverAt(100000) + .lifetimeId("1") + .willId("2") + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttSessionSignalFW signal = new MqttSessionSignalFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(MqttSessionSignalType.WILL.value(), signal.kind()); + assertEquals("client-1", signal.will().clientId().asString()); + assertEquals(20, signal.will().delay()); + assertEquals(100000, signal.will().deliverAt()); + assertEquals("1", signal.will().lifetimeId().asString()); + assertEquals("2", signal.will().willId().asString()); + assertEquals("zilla-1", signal.will().instanceId().asString()); + } + + @Test + public void shouldEncodeWillSignalUnknownDeliverAt() + { + final byte[] array = MqttFunctions.sessionSignal() + .will() + .instanceId("zilla-1") + .clientId("client-1") + .delay(20) + .lifetimeId("1") + .willId("2") + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttSessionSignalFW signal = new MqttSessionSignalFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(MqttSessionSignalType.WILL.value(), signal.kind()); + assertEquals("client-1", signal.will().clientId().asString()); + assertEquals(20, signal.will().delay()); + assertEquals(-1, signal.will().deliverAt()); + assertEquals("1", signal.will().lifetimeId().asString()); + assertEquals("2", signal.will().willId().asString()); + assertEquals("zilla-1", signal.will().instanceId().asString()); + } + + @Test + public void shouldEncodeExpirySignal() + { + final byte[] array = MqttFunctions.sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(20) + .expireAt(100000) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttSessionSignalFW signal = new MqttSessionSignalFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(MqttSessionSignalType.EXPIRY.value(), signal.kind()); + assertEquals("client-1", signal.expiry().clientId().asString()); + assertEquals(20, signal.expiry().delay()); + assertEquals(100000, signal.expiry().expireAt()); + assertEquals("zilla-1", signal.expiry().instanceId().asString()); + } + + @Test + public void shouldEncodeExpirySignalUnknownExpiry() + { + final byte[] array = MqttFunctions.sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client-1") + .delay(20) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttSessionSignalFW signal = new MqttSessionSignalFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(MqttSessionSignalType.EXPIRY.value(), signal.kind()); + assertEquals("client-1", signal.expiry().clientId().asString()); + assertEquals("zilla-1", signal.expiry().instanceId().asString()); + assertEquals(20, signal.expiry().delay()); + assertEquals(-1, signal.expiry().expireAt()); } } diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/ConnectionIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/ConnectionIT.java new file mode 100644 index 0000000000..63a26568cb --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/ConnectionIT.java @@ -0,0 +1,119 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.application; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class ConnectionIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${app}/client.sent.abort/client", + "${app}/client.sent.abort/server"}) + public void shouldReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/connect.max.packet.size.exceeded/client", + "${app}/connect.max.packet.size.exceeded/server"}) + public void shouldNotReceivePublishPacketExceedingMaxPacketLimit() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/disconnect.after.subscribe.and.publish/client", + "${app}/disconnect.after.subscribe.and.publish/server"}) + public void shouldDisconnectAfterSubscribeAndPublish() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/connect.non.successful.connack/client", + "${app}/connect.non.successful.connack/server"}) + public void shouldResetWithReasonCodeOnNonSuccessfulConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/connect.non.successful.disconnect/client", + "${app}/connect.non.successful.disconnect/server"}) + public void shouldResetWithReasonCodeOnNonSuccessfulDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/connect.delegate.connack.properties/client", + "${app}/connect.delegate.connack.properties/server"}) + public void shouldDelegateConnackProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/connect.retain.not.supported/client", + "${app}/connect.retain.not.supported/server"}) + public void shouldConnectWithRetainNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/connect.reject.will.retain.not.supported/client", + "${app}/connect.reject.will.retain.not.supported/server"}) + public void shouldRejectConnectWillRetainNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/connect.maximum.qos.0/client", + "${app}/connect.maximum.qos.0/server"}) + public void shouldConnectWithMaximumQos0() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java new file mode 100644 index 0000000000..4f493f24b9 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java @@ -0,0 +1,165 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.application; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class PublishIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${app}/publish.one.message/client", + "${app}/publish.one.message/server"}) + public void shouldSendOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.one.message.subscribe.unfragmented/client", + "${app}/publish.one.message.subscribe.unfragmented/server"}) + public void shouldSendOneMessageSubscribeUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.multiple.messages/client", + "${app}/publish.multiple.messages/server"}) + public void shouldSendMultipleMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.with.user.property/client", + "${app}/publish.with.user.property/server"}) + public void shouldSendWithUserProperty() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.with.user.properties.repeated/client", + "${app}/publish.with.user.properties.repeated/server"}) + public void shouldSendWithRepeatedUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.with.user.properties.distinct/client", + "${app}/publish.with.user.properties.distinct/server"}) + public void shouldSendWithDistinctUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.message.with.topic.alias/client", + "${app}/publish.message.with.topic.alias/server"}) + public void shouldSendMessageWithTopicAlias() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.messages.with.topic.alias.distinct/client", + "${app}/publish.messages.with.topic.alias.distinct/server"}) + public void shouldSendMessagesWithTopicAliasDistinct() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.messages.with.topic.alias.repeated/client", + "${app}/publish.messages.with.topic.alias.repeated/server"}) + public void shouldSendMessagesWithTopicAliasRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.messages.with.topic.alias.replaced/client", + "${app}/publish.messages.with.topic.alias.replaced/server"}) + public void shouldSendMessagesWithTopicAliasesReplaced() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.3.2-7] + @Test + @Specification({ + "${app}/publish.messages.with.topic.alias.invalid.scope/client", + "${app}/publish.messages.with.topic.alias.invalid.scope/server"}) + public void shouldSendMessagesWithTopicAliasInvalidScope() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.retained/client", + "${app}/publish.retained/server"}) + public void shouldPublishRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.empty.retained.message/client", + "${app}/publish.empty.retained.message/server"}) + public void shouldSendEmptyRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/publish.empty.message/client", + "${app}/publish.empty.message/server"}) + public void shouldSendEmptyMessage() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SessionIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SessionIT.java new file mode 100644 index 0000000000..ce701e9387 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SessionIT.java @@ -0,0 +1,202 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.application; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class SessionIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + + @Test + @Specification({ + "${app}/session.connect/client", + "${app}/session.connect/server"}) + public void shouldConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.connect.with.session.expiry/client", + "${app}/session.connect.with.session.expiry/server"}) + public void shouldConnectWithSessionExpiry() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.connect.override.session.expiry/client", + "${app}/session.connect.override.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiry() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.exists.clean.start/client", + "${app}/session.exists.clean.start/server"}) + public void shouldRemoveSessionAtCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.will.message.abort/client", + "${app}/session.will.message.abort/server"}) + public void shouldAbortSessionStreamWhenWillDelivery() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.will.message.normal.disconnect/client", + "${app}/session.will.message.normal.disconnect/server"}) + public void shouldSendReasonForEndAfterNormalClientDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.subscribe/client", + "${app}/session.subscribe/server"}) + public void shouldSubscribeSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-15] + @Test + @Specification({ + "${app}/session.will.message.retain/client", + "${app}/session.will.message.retain/server"}) + public void shouldConnectWithWillMessageWithRetain() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.abort.reconnect.non.clean.start/client", + "${app}/session.abort.reconnect.non.clean.start/server"}) + public void shouldReconnectNonCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.client.takeover/client", + "${app}/session.client.takeover/server"}) + public void shouldTakeOverSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.unsubscribe.after.subscribe/client", + "${app}/session.unsubscribe.after.subscribe/server"}) + public void shouldUnsubscribeAndUpdateSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.subscribe.via.session.state/client", + "${app}/session.subscribe.via.session.state/server"}) + public void shouldReceiveMessageSubscribedViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.unsubscribe.via.session.state/client", + "${app}/session.unsubscribe.via.session.state/server"}) + public void shouldUnsubscribeViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.unsubscribe.after.subscribe.deferred/client", + "${app}/session.unsubscribe.after.subscribe.deferred/server"}) + public void shouldUnsubscribeAfterSubscribeDeferred() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.server.redirect.before.connack/client", + "${app}/session.server.redirect.before.connack/server"}) + public void shouldRedirectBeforeConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.server.redirect.after.connack/client", + "${app}/session.server.redirect.after.connack/server"}) + public void shouldRedirectAfterConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.subscribe.multiple.isolated/client", + "${app}/session.subscribe.multiple.isolated/server"}) + public void shouldSubscribeMultipleSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/session.subscribe.publish.routing/client", + "${app}/session.subscribe.publish.routing/server"}) + public void shouldSubscribeAndPublishToNonDefaultRoute() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SubscribeIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SubscribeIT.java new file mode 100644 index 0000000000..89c231aafb --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/SubscribeIT.java @@ -0,0 +1,263 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.application; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class SubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${app}/subscribe.topic.filter.single.exact/client", + "${app}/subscribe.topic.filter.single.exact/server"}) + public void shouldFilterExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filter.multi.level.wildcard/client", + "${app}/subscribe.topic.filter.multi.level.wildcard/server"}) + public void shouldFilterMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filter.single.level.wildcard/client", + "${app}/subscribe.topic.filter.single.level.wildcard/server"}) + public void shouldFilterSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filter.single.and.multi.level.wildcard/client", + "${app}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) + public void shouldFilterSingleAndMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filter.two.single.level.wildcard/client", + "${app}/subscribe.topic.filter.two.single.level.wildcard/server"}) + public void shouldFilterTwoSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.aggregated.both.exact/client", + "${app}/subscribe.topic.filters.aggregated.both.exact/server"}) + public void shouldFilterAggregatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.isolated.both.exact/client", + "${app}/subscribe.topic.filters.isolated.both.exact/server"}) + public void shouldFilterIsolatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.disjoint.wildcards/client", + "${app}/subscribe.topic.filters.disjoint.wildcards/server"}) + public void shouldFilterDisjointWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.overlapping.wildcards/client", + "${app}/subscribe.topic.filters.overlapping.wildcards/server"}) + public void shouldFilterOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.isolated.both.wildcard/client", + "${app}/subscribe.topic.filters.isolated.both.wildcard/server"}) + public void shouldFilterIsolatedBothWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", + "${app}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) + public void shouldFilterAggregatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.isolated.exact.and.wildcard/client", + "${app}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) + public void shouldFilterIsolatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.one.message/client", + "${app}/subscribe.one.message/server"}) + public void shouldReceiveOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.one.message.user.properties.unaltered/client", + "${app}/subscribe.one.message.user.properties.unaltered/server"}) + public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.publish.no.local/client", + "${app}/subscribe.publish.no.local/server"}) + public void shouldNotReceivePublishLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.receive.message/client", + "${app}/subscribe.receive.message/server"}) + public void shouldReceiveOneMessageAfterPublish() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.receive.message.wildcard/client", + "${app}/subscribe.receive.message.wildcard/server"}) + public void shouldReceiveOneMessageWithPatternTopic() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.get.retained.as.published/client", + "${app}/subscribe.get.retained.as.published/server"}) + public void shouldReceiveRetainedAsPublished() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.one.message.receive.response.topic.and.correlation.data/client", + "${app}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) + public void shouldReceiveCorrelationData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.qos0.replay.retained.no.packet.id/client", + "${app}/subscribe.qos0.replay.retained.no.packet.id/server"}) + public void shouldReceiveAndReplayRetainedQos0() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.qos0.publish.retained.no.replay/client", + "${app}/subscribe.qos0.publish.retained.no.replay/server"}) + public void shouldNotReplayRetained() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.receive.messages.topic.alias.repeated/client", + "${app}/subscribe.receive.messages.topic.alias.repeated/server"}) + public void shouldReceiveMessagesTopicAliasRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.topic.filters.non.successful/client", + "${app}/subscribe.topic.filters.non.successful/server"}) + public void shouldFilterNonSuccessful() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.reconnect.publish.no.subscription/client", + "${app}/subscribe.reconnect.publish.no.subscription/server"}) + public void shouldReceiveReconnectNoSubscription() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/subscribe.publish.invalid.affinity/client", + "${app}/subscribe.publish.invalid.affinity/server"}) + public void shouldAbortSubscribeAndPublishInvalidAffinity() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/UnsubscribeIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/UnsubscribeIT.java new file mode 100644 index 0000000000..d52937fc19 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/UnsubscribeIT.java @@ -0,0 +1,83 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.application; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class UnsubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("app", "io/aklivity/zilla/specs/binding/mqtt/streams/application"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${app}/unsubscribe.after.subscribe/client", + "${app}/unsubscribe.after.subscribe/server"}) + public void shouldAcknowledge() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/unsubscribe.aggregated.topic.filters.both.exact/client", + "${app}/unsubscribe.aggregated.topic.filters.both.exact/server"}) + public void shouldAcknowledgeAggregatedTopicFiltersBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/unsubscribe.topic.filter.single/client", + "${app}/unsubscribe.topic.filter.single/server"}) + public void shouldAcknowledgeSingleTopicFilters() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/unsubscribe.publish.unfragmented/client", + "${app}/unsubscribe.publish.unfragmented/server"}) + public void shouldAcknowledgeAndPublishUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${app}/unsubscribe.topic.filters.non.successful/client", + "${app}/unsubscribe.topic.filters.non.successful/server"}) + public void shouldAcknowledgeNonSuccessful() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/ConnectionIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/ConnectionIT.java new file mode 100644 index 0000000000..928fb50e36 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/ConnectionIT.java @@ -0,0 +1,475 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class ConnectionIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${net}/connect.successful/client", + "${net}/connect.successful/server"}) + public void shouldConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.username.authentication.successful/client", + "${net}/connect.username.authentication.successful/server"}) + public void shouldAuthenticateUsernameAndConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.username.authentication.failed/client", + "${net}/connect.username.authentication.failed/server"}) + public void shouldFailUsernameAuthentication() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.password.authentication.successful/client", + "${net}/connect.password.authentication.successful/server"}) + public void shouldAuthenticatePasswordAndConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.password.authentication.failed/client", + "${net}/connect.password.authentication.failed/server"}) + public void shouldFailPasswordAuthentication() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.server.assigned.client.id/client", + "${net}/connect.server.assigned.client.id/server"}) + public void shouldConnectWithServerAssignedClientId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.reject.missing.client.id/client", + "${net}/connect.reject.missing.client.id/server"}) + public void shouldRejectMissingClientId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/disconnect/client", + "${net}/disconnect/server"}) + public void shouldConnectThenDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.invalid.protocol.version/client", + "${net}/connect.invalid.protocol.version/server"}) + public void shouldRejectInvalidProtocolVersion() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.invalid.flags/client", + "${net}/connect.invalid.flags/server"}) + public void shouldRejectMalformedConnectPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.invalid.authentication.method/client", + "${net}/connect.invalid.authentication.method/server"}) + public void shouldRejectBadAuthenticationMethod() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/disconnect.reject.invalid.fixed.header.flags/client", + "${net}/disconnect.reject.invalid.fixed.header.flags/server"}) + public void shouldRejectMalformedDisconnectPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.reject.second.connect/client", + "${net}/connect.reject.second.connect/server"}) + public void shouldRejectSecondConnectPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.reject.topic.alias.maximum.repeated/client", + "${net}/connect.reject.topic.alias.maximum.repeated/server"}) + public void shouldRejectConnectWhenTopicAliasMaximumRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.successful.fragmented/client", + "${net}/connect.successful.fragmented/server"}) + public void shouldConnectFragmented() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.0-1] + @Test + @Specification({ + "${net}/connect.reject.other.packet.before.connect/client", + "${net}/connect.reject.other.packet.before.connect/server"}) + public void shouldRejectOtherPacketBeforeConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/client.sent.close/client", + "${net}/client.sent.close/server"}) + public void shouldReceiveClientSentClose() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/client.sent.abort/client", + "${net}/client.sent.abort/server"}) + public void shouldReceiveClientSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/client.sent.reset/client", + "${net}/client.sent.reset/server"}) + public void shouldReceiveClientSentReset() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/disconnect.after.keep.alive.timeout/client", + "${net}/disconnect.after.keep.alive.timeout/server"}) + public void shouldDisconnectClientAfterKeepAliveTimeout() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-21], [MQTT-3.2.2-21] + @Test + @Specification({ + "${net}/connect.server.defined.keep.alive/client", + "${net}/connect.server.defined.keep.alive/server"}) + public void shouldConnectAndUseServerDefinedKeepAlive() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.timeout.before.connect/client", + "${net}/connect.timeout.before.connect/server"}) + public void shouldTimeoutBeforeConnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.maximum.qos.0/client", + "${net}/connect.maximum.qos.0/server"}) + public void shouldConnectWithMaximumQos0() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.retain.not.supported/client", + "${net}/connect.retain.not.supported/server"}) + public void shouldConnectWithRetainNotSupported() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.2.2-13] + @Test + @Specification({ + "${net}/connect.reject.will.retain.not.supported/client", + "${net}/connect.reject.will.retain.not.supported/server"}) + public void shouldRejectConnectWillRetainNotSupported() throws Exception + { + k3po.finish(); + } + + @Ignore + @Test + @Specification({ + "${net}/connect.reject.username.not.authorized/client", + "${net}/connect.reject.username.not.authorized/server"}) + public void shouldRejectConnectWithUsernameNotAuthorized() throws Exception + { + k3po.finish(); + } + + @Ignore + @Test + @Specification({ + "${net}/connect.reject.password.not.authorized/client", + "${net}/connect.reject.password.not.authorized/server"}) + public void shouldRejectConnectWithPasswordNotAuthorized() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.will.invalid.will.qos/client", + "${net}/connect.will.invalid.will.qos/server"}) + public void shouldRejectInvalidWillQos() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.will.reject.will.qos.1.without.will.flag/client", + "${net}/connect.will.reject.will.qos.1.without.will.flag/server"}) + public void shouldRejectWillQos1WithoutWillFlag() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.will.reject.will.qos.2.without.will.flag/client", + "${net}/connect.will.reject.will.qos.2.without.will.flag/server"}) + public void shouldRejectWillQos2WithoutWillFlag() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.will.reject.will.retain.without.will.flag/client", + "${net}/connect.will.reject.will.retain.without.will.flag/server"}) + public void shouldRejectWillRetainWithoutWillFlag() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-9] + @Test + @Specification({ + "${net}/connect.reject.will.payload.missing/client", + "${net}/connect.reject.will.payload.missing/server"}) + public void shouldRejectConnectWillPayloadMissing() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-9] + @Test + @Specification({ + "${net}/connect.reject.will.properties.missing/client", + "${net}/connect.reject.will.properties.missing/server"}) + public void shouldRejectConnectWillPropertiesMissing() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-9] + @Test + @Specification({ + "${net}/connect.reject.will.topic.missing/client", + "${net}/connect.reject.will.topic.missing/server"}) + public void shouldRejectConnectWillTopicNotMissing() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-16] + @Test + @Specification({ + "${net}/connect.reject.username.flag.missing/client", + "${net}/connect.reject.username.flag.missing/server"}) + public void shouldRejectUsernameUserFlagMissing() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-18] + @Test + @Specification({ + "${net}/connect.reject.password.no.password.flag/client", + "${net}/connect.reject.password.no.password.flag/server"}) + public void shouldRejectPasswordWhenMissingPasswordFlag() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-17] + @Test + @Specification({ + "${net}/connect.reject.username.flag.only/client", + "${net}/connect.reject.username.flag.only/server"}) + public void shouldRejectConnectUsernameFlagOnly() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-19] + @Test + @Specification({ + "${net}/connect.reject.password.flag.no.password/client", + "${net}/connect.reject.password.flag.no.password/server"}) + public void shouldRejectPasswordFlagWhenMissingPassword() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-24] + @Test + @Specification({ + "${net}/connect.max.packet.size.exceeded/client", + "${net}/connect.max.packet.size.exceeded/server"}) + public void shouldNotReceivePublishPacketExceedingMaxPacketLimit() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.reject.packet.too.large/client", + "${net}/connect.reject.packet.too.large/server"}) + public void shouldRejectPacketTooLarge() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.subscribe.unfragmented/client", + "${net}/connect.subscribe.unfragmented/server"}) + public void shouldConnectAndSubscribeUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/disconnect.after.subscribe.and.publish/client", + "${net}/disconnect.after.subscribe.and.publish/server"}) + public void shouldDisconnectAfterSubscribeAndPublish() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/disconnect.invalid.session.expiry/client", + "${net}/disconnect.invalid.session.expiry/server"}) + public void shouldRejectInvalidSessionExpiryOnDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.non.successful.connack/client", + "${net}/connect.non.successful.connack/server"}) + public void shouldResetWithReasonCodeOnNonSuccessfulConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.non.successful.disconnect/client", + "${net}/connect.non.successful.disconnect/server"}) + public void shouldResetWithReasonCodeOnNonSuccessfulDisconnect() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/connect.delegate.connack.properties/client", + "${net}/connect.delegate.connack.properties/server"}) + public void shouldDelegateConnackProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/disconnect.no.reasoncode.no.properties/client", + "${net}/disconnect.no.reasoncode.no.properties/server"}) + public void shouldConnectThenDisconnectWithNoReasonCodeNoProperties() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PingIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PingIT.java new file mode 100644 index 0000000000..8409d47310 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PingIT.java @@ -0,0 +1,74 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class PingIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${net}/ping/client", + "${net}/ping/server"}) + public void shouldConnectThenPingRequestResponse() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/ping.server.override.keep.alive/client", + "${net}/ping.server.override.keep.alive/server"}) + public void shouldPingServerOverridesKeepAlive() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/ping.no.pingresp/client", + "${net}/ping.no.pingresp/server"}) + public void shouldCloseWhenPingRequestNoResponseInTimeout() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/ping.keep.alive/client", + "${net}/ping.keep.alive/server"}) + public void shouldPingAtKeepAliveInterval() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PublishIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PublishIT.java new file mode 100644 index 0000000000..8911a941c9 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/PublishIT.java @@ -0,0 +1,312 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class PublishIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${net}/publish.one.message/client", + "${net}/publish.one.message/server"}) + public void shouldSendOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.multiple.messages/client", + "${net}/publish.multiple.messages/server"}) + public void shouldSendMultipleMessages() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.multiple.messages.unfragmented/client", + "${net}/publish.multiple.messages.unfragmented/server"}) + public void shouldSendMultipleMessagesUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.multiple.messages.with.delay/client", + "${net}/publish.multiple.messages.with.delay/server"}) + public void shouldSendMultipleMessagesWithDelay() throws Exception + { + k3po.start(); + k3po.awaitBarrier("PUBLISHED_MESSAGE_TWO"); + k3po.notifyBarrier("PUBLISH_MESSAGE_THREE"); + k3po.finish(); + } + + // [MQTT-2.2.1-2] + @Test + @Specification({ + "${net}/publish.reject.qos0.with.packet.id/client", + "${net}/publish.reject.qos0.with.packet.id/server"}) + public void shouldRejectQos0WithPackedId() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.2.2-9], [MQTT-3.2.2-12] + @Test + @Specification({ + "${net}/publish.reject.qos1.not.supported/client", + "${net}/publish.reject.qos1.not.supported/server"}) + public void shouldRejectQos1NotSupported() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.2.2-9], [MQTT-3.2.2-12] + @Test + @Specification({ + "${net}/publish.reject.qos2.not.supported/client", + "${net}/publish.reject.qos2.not.supported/server"}) + public void shouldRejectQos2NotSupported() throws Exception + { + k3po.finish(); + } + + // [MQTT-2.2.1-3] + @Test + @Specification({ + "${net}/publish.reject.qos1.without.packet.id/client", + "${net}/publish.reject.qos1.without.packet.id/server"}) + public void shouldRejectQos1WithoutPackedId() throws Exception + { + k3po.finish(); + } + + // [MQTT-2.2.1-3] + @Test + @Specification({ + "${net}/publish.reject.qos2.without.packet.id/client", + "${net}/publish.reject.qos2.without.packet.id/server"}) + public void shouldRejectQos2WithoutPackedId() throws Exception + { + k3po.finish(); + } + + // [MQTT-2.2.1-3] + @Test + @Specification({ + "${net}/publish.reject.invalid.payload.format/client", + "${net}/publish.reject.invalid.payload.format/server"}) + public void shouldRejectInvalidPayloadFormat() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.3.4-6] + @Test + @Specification({ + "${net}/publish.reject.client.sent.subscription.id/client", + "${net}/publish.reject.client.sent.subscription.id/server"}) + public void shouldRejectClientSentSubscriptionId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.reject.topic.alias.exceeds.maximum/client", + "${net}/publish.reject.topic.alias.exceeds.maximum/server"}) + public void shouldRejectWhenTopicAliasExceedsThanMaximum() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.2.2-14] + @Test + @Specification({ + "${net}/publish.reject.retain.not.supported/client", + "${net}/publish.reject.retain.not.supported/server"}) + public void shouldRejectRetainedRetainNotSupported() throws Exception + { + k3po.finish(); + } + + + @Test + @Specification({ + "${net}/publish.reject.topic.alias.repeated/client", + "${net}/publish.reject.topic.alias.repeated/server"}) + public void shouldRejectWhenTopicAliasRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.topic.not.routed/client", + "${net}/publish.topic.not.routed/server"}) + public void shouldRejectTopicNotRouted() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.with.user.property/client", + "${net}/publish.with.user.property/server"}) + public void shouldSendWithUserProperty() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.with.user.properties.repeated/client", + "${net}/publish.with.user.properties.repeated/server"}) + public void shouldSendWithRepeatedUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.with.user.properties.distinct/client", + "${net}/publish.with.user.properties.distinct/server"}) + public void shouldSendWithDistinctUserProperties() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.message.with.topic.alias/client", + "${net}/publish.message.with.topic.alias/server"}) + public void shouldSendMessageWithTopicAlias() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.messages.with.topic.alias.distinct/client", + "${net}/publish.messages.with.topic.alias.distinct/server"}) + public void shouldSendMessagesWithTopicAliasDistinct() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.messages.with.topic.alias.repeated/client", + "${net}/publish.messages.with.topic.alias.repeated/server"}) + public void shouldSendMessagesWithTopicAliasRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.messages.with.topic.alias.replaced/client", + "${net}/publish.messages.with.topic.alias.replaced/server"}) + public void shouldSendMessagesWithTopicAliasReplaced() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.3.2-7] + @Test + @Specification({ + "${net}/publish.messages.with.topic.alias.invalid.scope/client", + "${net}/publish.messages.with.topic.alias.invalid.scope/server"}) + public void shouldSendMessagesWithTopicAliasInvalidScope() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.retained/client", + "${net}/publish.retained/server"}) + public void shouldPublishRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.empty.retained.message/client", + "${net}/publish.empty.retained.message/server"}) + public void shouldSendEmptyRetainedMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.empty.message/client", + "${net}/publish.empty.message/server"}) + public void shouldSendEmptyMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.publish.no.local/client", + "${net}/subscribe.publish.no.local/server"}) + public void shouldSubscribeThenSendNoLocal() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.one.message.subscribe.unfragmented/client", + "${net}/publish.one.message.subscribe.unfragmented/server"}) + public void shouldPublishOneMessageThenSubscribeUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/publish.reject.packet.too.large/client", + "${net}/publish.reject.packet.too.large/server"}) + public void shouldRejectPacketTooLarge() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SessionIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SessionIT.java new file mode 100644 index 0000000000..5862d0c27b --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SessionIT.java @@ -0,0 +1,194 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class SessionIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + + @Test + @Specification({ + "${net}/session.connect.with.session.expiry/client", + "${net}/session.connect.with.session.expiry/server"}) + public void shouldConnectWithSessionExpiry() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.connect.override.session.expiry/client", + "${net}/session.connect.override.session.expiry/server"}) + public void shouldConnectServerOverridesSessionExpiry() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-5], [MQTT-3.1.2-23] + @Test + @Specification({ + "${net}/session.abort.reconnect.non.clean.start/client", + "${net}/session.abort.reconnect.non.clean.start/server"}) + public void shouldReconnectNonCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.client.takeover/client", + "${net}/session.client.takeover/server"}) + public void shouldTakeOverSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.subscribe/client", + "${net}/session.subscribe/server"}) + public void shouldSubscribeSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.will.message.disconnect.with.will.message/client", + "${net}/session.will.message.disconnect.with.will.message/server"}) + public void shouldConnectWithWillMessageThenDisconnectWithWillMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.exists.clean.start/client", + "${net}/session.exists.clean.start/server"}) + public void shouldRemoveSessionAtCleanStart() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.will.message.no.ping.within.keep.alive/client", + "${net}/session.will.message.no.ping.within.keep.alive/server"}) + public void shouldConnectWithWillMessageThenNoPingWithinKeepAlive() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.will.message.normal.disconnect/client", + "${net}/session.will.message.normal.disconnect/server"}) + public void shouldConnectWithWillMessageThenNormalDisconnect() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.1.2-15] + @Test + @Specification({ + "${net}/session.will.message.retain/client", + "${net}/session.will.message.retain/server"}) + public void shouldConnectWithWillMessageWithRetain() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.unsubscribe.after.subscribe/client", + "${net}/session.unsubscribe.after.subscribe/server"}) + public void shouldUnsubscribeAndUpdateSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.subscribe.via.session.state/client", + "${net}/session.subscribe.via.session.state/server"}) + public void shouldReceiveMessageSubscribedViaSessionState() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.unsubscribe.after.subscribe.deferred/client", + "${net}/session.unsubscribe.after.subscribe.deferred/server"}) + public void shouldUnsubscribeAfterSubscribeDeferred() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.server.redirect.before.connack/client", + "${net}/session.server.redirect.before.connack/server"}) + public void shouldRedirectBeforeConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.server.redirect.after.connack/client", + "${net}/session.server.redirect.after.connack/server"}) + public void shouldRedirectAfterConnack() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.subscribe.multiple.isolated/client", + "${net}/session.subscribe.multiple.isolated/server"}) + public void shouldSubscribeMultipleSaveSubscriptionsInSession() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/session.subscribe.publish.routing/client", + "${net}/session.subscribe.publish.routing/server"}) + public void shouldSubscribeAndPublishToNonDefaultRoute() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SubscribeIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SubscribeIT.java new file mode 100644 index 0000000000..cd7a26499c --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/SubscribeIT.java @@ -0,0 +1,358 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class SubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + @Test + @Specification({ + "${net}/subscribe.one.message/client", + "${net}/subscribe.one.message/server"}) + public void shouldReceiveOneMessage() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.one.message.user.properties.unaltered/client", + "${net}/subscribe.one.message.user.properties.unaltered/server"}) + public void shouldReceiveOneMessageWithUserPropertiesUnaltered() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.receive.message.wildcard/client", + "${net}/subscribe.receive.message.wildcard/server"}) + public void shouldReceiveOneMessageWithPatternTopic() throws Exception + { + k3po.finish(); + } + + // [MQTT-2.2.1-3] + @Test + @Specification({ + "${net}/subscribe.reject.missing.packet.id/client", + "${net}/subscribe.reject.missing.packet.id/server"}) + public void shouldRejectWithoutPacketId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.reject.missing.topic.filters/client", + "${net}/subscribe.reject.missing.topic.filters/server"}) + public void shouldRejectWithMissingTopicFilters() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.invalid.topic.filter/client", + "${net}/subscribe.invalid.topic.filter/server"}) + public void shouldRejectInvalidTopicFilter() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filter.single.exact/client", + "${net}/subscribe.topic.filter.single.exact/server"}) + public void shouldFilterExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filter.multi.level.wildcard/client", + "${net}/subscribe.topic.filter.multi.level.wildcard/server"}) + public void shouldFilterMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filter.single.level.wildcard/client", + "${net}/subscribe.topic.filter.single.level.wildcard/server"}) + public void shouldFilterSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filter.two.single.level.wildcard/client", + "${net}/subscribe.topic.filter.two.single.level.wildcard/server"}) + public void shouldFilterTwoSingleLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filter.single.and.multi.level.wildcard/client", + "${net}/subscribe.topic.filter.single.and.multi.level.wildcard/server"}) + public void shouldFilterSingleAndMultiLevelWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.disjoint.wildcards/client", + "${net}/subscribe.topic.filters.disjoint.wildcards/server"}) + public void shouldFilterDisjointWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.overlapping.wildcards/client", + "${net}/subscribe.topic.filters.overlapping.wildcards/server"}) + public void shouldFilterOverlappingWildcard() throws Exception + { + k3po.finish(); + } + + + @Test + @Specification({ + "${net}/subscribe.reject.topic.filter.invalid.wildcard/client", + "${net}/subscribe.reject.topic.filter.invalid.wildcard/server"}) + public void shouldRejectTopicFilterInvalidWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.aggregated.both.exact/client", + "${net}/subscribe.topic.filters.aggregated.both.exact/server"}) + public void shouldFilterAggregatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.exact/client", + "${net}/subscribe.topic.filters.isolated.both.exact/server"}) + public void shouldFilterIsolatedBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.exact.no.subscription.id/client", + "${net}/subscribe.topic.filters.isolated.both.exact.no.subscription.id/server"}) + public void shouldFilterIsolatedBothExactNoSubscriptionId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.isolated.both.wildcard/client", + "${net}/subscribe.topic.filters.isolated.both.wildcard/server"}) + public void shouldFilterIsolatedBothWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.aggregated.exact.and.wildcard/client", + "${net}/subscribe.topic.filters.aggregated.exact.and.wildcard/server"}) + public void shouldFilterAggregatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.isolated.exact.and.wildcard/client", + "${net}/subscribe.topic.filters.isolated.exact.and.wildcard/server"}) + public void shouldFilterIsolatedExactAndWildcard() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.invalid.fixed.header.flags/client", + "${net}/subscribe.invalid.fixed.header.flags/server"}) + public void shouldRejectMalformedPacket() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.reject.no.local/client", + "${net}/subscribe.reject.no.local/server"}) + public void shouldRejectNoLocal() throws Exception + { + k3po.finish(); + } + + + // [MQTT-3.3.2-15], [MQTT-3.3.2-16] + @Test + @Specification({ + "${net}/subscribe.one.message.receive.response.topic.and.correlation.data/client", + "${net}/subscribe.one.message.receive.response.topic.and.correlation.data/server"}) + public void shouldReceiveCorrelationData() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.one.message.with.invalid.subscription.id/client", + "${net}/subscribe.one.message.with.invalid.subscription.id/server"}) + public void shouldReceiveOneMessageWithInvalidSubscriptionId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.receive.message/client", + "${net}/subscribe.receive.message/server"}) + public void shouldReceiveOneMessageAfterPublish() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.get.retained.as.published/client", + "${net}/subscribe.get.retained.as.published/server"}) + public void shouldReceiveRetainedAsPublished() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.8.3-5] + @Test + @Specification({ + "${net}/subscribe.reject.malformed.subscription.options/client", + "${net}/subscribe.reject.malformed.subscription.options/server"}) + public void shouldRejectMalformedSubscriptionOptions() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.reject.wildcard.subscriptions.not.supported/client", + "${net}/subscribe.reject.wildcard.subscriptions.not.supported/server"}) + public void shouldRejectWildcardSubscriptionsNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.reject.subscription.ids.not.supported/client", + "${net}/subscribe.reject.subscription.ids.not.supported/server"}) + public void shouldRejectSubscriptionIdentifiersNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.reject.shared.subscriptions.not.supported/client", + "${net}/subscribe.reject.shared.subscriptions.not.supported/server"}) + public void shouldRejectSharedSubscriptionsNotSupported() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.qos0.replay.retained.no.packet.id/client", + "${net}/subscribe.qos0.replay.retained.no.packet.id/server"}) + public void shouldReceiveAndReplayRetainedQos0() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.qos0.publish.retained.no.replay/client", + "${net}/subscribe.qos0.publish.retained.no.replay/server"}) + public void shouldNotReplayRetained() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.receive.messages.topic.alias.repeated/client", + "${net}/subscribe.receive.messages.topic.alias.repeated/server"}) + public void shouldReceiveMessagesTopicAliasRepeated() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.topic.filters.non.successful/client", + "${net}/subscribe.topic.filters.non.successful/server"}) + public void shouldFilterNonSuccessful() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/subscribe.reconnect.publish.no.subscription/client", + "${net}/subscribe.reconnect.publish.no.subscription/server"}) + public void shouldReceiveReconnectNoSubscription() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/UnsubscribeIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/UnsubscribeIT.java new file mode 100644 index 0000000000..3fc3f53936 --- /dev/null +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/network/UnsubscribeIT.java @@ -0,0 +1,123 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.aklivity.zilla.specs.binding.mqtt.streams.network; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.rules.RuleChain.outerRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.kaazing.k3po.junit.annotation.Specification; +import org.kaazing.k3po.junit.rules.K3poRule; + +public class UnsubscribeIT +{ + private final K3poRule k3po = new K3poRule() + .addScriptRoot("net", "io/aklivity/zilla/specs/binding/mqtt/streams/network"); + + private final TestRule timeout = new DisableOnDebug(new Timeout(5, SECONDS)); + + @Rule + public final TestRule chain = outerRule(k3po).around(timeout); + + // [MQTT-2.2.1-3] + @Test + @Specification({ + "${net}/unsubscribe.reject.missing.packet.id/client", + "${net}/unsubscribe.reject.missing.packet.id/server"}) + public void shouldRejectWithoutPacketId() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/unsubscribe.after.subscribe/client", + "${net}/unsubscribe.after.subscribe/server"}) + public void shouldAcknowledge() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.10.4-5] + @Test + @Specification({ + "${net}/unsubscribe.no.matching.subscription/client", + "${net}/unsubscribe.no.matching.subscription/server"}) + public void shouldAcknowledgeNoMatchingSubscription() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/unsubscribe.aggregated.topic.filters.both.exact/client", + "${net}/unsubscribe.aggregated.topic.filters.both.exact/server"}) + public void shouldAcknowledgeAggregatedTopicFiltersBothExact() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/unsubscribe.topic.filter.single/client", + "${net}/unsubscribe.topic.filter.single/server"}) + public void shouldAcknowledgeSingleTopicFilters() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.10.1-1] + @Test + @Specification({ + "${net}/unsubscribe.reject.invalid.fixed.header.flags/client", + "${net}/unsubscribe.reject.invalid.fixed.header.flags/server"}) + public void shouldRejectMalformedPacket() throws Exception + { + k3po.finish(); + } + + // [MQTT-3.10.3-2] + @Test + @Specification({ + "${net}/unsubscribe.reject.no.topic.filter/client", + "${net}/unsubscribe.reject.no.topic.filter/server"}) + public void shouldRejectNoTopicFilter() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/unsubscribe.publish.unfragmented/client", + "${net}/unsubscribe.publish.unfragmented/server"}) + public void shouldAcknowledgeAndPublishUnfragmented() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${net}/unsubscribe.topic.filters.non.successful/client", + "${net}/unsubscribe.topic.filters.non.successful/server"}) + public void shouldAcknowledgeNonSuccessful() throws Exception + { + k3po.finish(); + } +} diff --git a/specs/binding-proxy.spec/pom.xml b/specs/binding-proxy.spec/pom.xml index 3871d6fc6a..73fdd2eefb 100644 --- a/specs/binding-proxy.spec/pom.xml +++ b/specs/binding-proxy.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-sse-kafka.spec/pom.xml b/specs/binding-sse-kafka.spec/pom.xml index e6c4b2b8d1..c6a1fdb188 100644 --- a/specs/binding-sse-kafka.spec/pom.xml +++ b/specs/binding-sse-kafka.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/client.rpt b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/client.rpt index a9b8af7a00..7d6a3b1061 100644 --- a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/client.rpt +++ b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/client.rpt @@ -57,6 +57,7 @@ read "Hello, again" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/server.rpt b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/server.rpt index 085878d37b..f2e0624691 100644 --- a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/server.rpt +++ b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.etag/server.rpt @@ -63,6 +63,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/client.rpt b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/client.rpt index aceeba26e0..a26e271b43 100644 --- a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/client.rpt +++ b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/client.rpt @@ -53,6 +53,7 @@ read "Hello, again" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/server.rpt b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/server.rpt index 999c278a0c..1bf51d9003 100644 --- a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/server.rpt +++ b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages.with.null.key/server.rpt @@ -59,6 +59,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/client.rpt b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/client.rpt index 7c455f08a9..3cf2256370 100644 --- a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/client.rpt +++ b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/client.rpt @@ -55,6 +55,7 @@ read "Hello, again" read advised zilla:flush ${kafka:matchFlushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/server.rpt b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/server.rpt index 889af16b13..ddfd07e530 100644 --- a/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/server.rpt +++ b/specs/binding-sse-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/sse/kafka/streams/kafka/server.sent.messages/server.rpt @@ -61,6 +61,7 @@ write flush write advise zilla:flush ${kafka:flushEx() .typeId(zilla:id("kafka")) .merged() + .fetch() .progress(0, 2, 2, 2) .build() .build()} diff --git a/specs/binding-sse.spec/pom.xml b/specs/binding-sse.spec/pom.xml index a4af04db13..9ff1407e61 100644 --- a/specs/binding-sse.spec/pom.xml +++ b/specs/binding-sse.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-tcp.spec/pom.xml b/specs/binding-tcp.spec/pom.xml index 344e45c0f7..a4c49db30e 100644 --- a/specs/binding-tcp.spec/pom.xml +++ b/specs/binding-tcp.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-tls.spec/pom.xml b/specs/binding-tls.spec/pom.xml index 9dfa3350ef..a7b4002a9c 100644 --- a/specs/binding-tls.spec/pom.xml +++ b/specs/binding-tls.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/binding-ws.spec/pom.xml b/specs/binding-ws.spec/pom.xml index a4a0785409..81c9adfdbd 100644 --- a/specs/binding-ws.spec/pom.xml +++ b/specs/binding-ws.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/engine.spec/NOTICE b/specs/engine.spec/NOTICE index 17c8dd9260..eb35495f05 100644 --- a/specs/engine.spec/NOTICE +++ b/specs/engine.spec/NOTICE @@ -14,7 +14,6 @@ under the License. This project includes: agrona under The Apache License, Version 2.0 ANTLR 4 Runtime under BSD-3-Clause - Hamcrest Core under New BSD License ICU4J under Unicode/ICU License Jakarta JSON Processing API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception Java Unified Expression Language API under The Apache Software License, Version 2.0 diff --git a/specs/engine.spec/pom.xml b/specs/engine.spec/pom.xml index 6f12049978..9708996de0 100644 --- a/specs/engine.spec/pom.xml +++ b/specs/engine.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/exporter-prometheus.spec/pom.xml b/specs/exporter-prometheus.spec/pom.xml index 3a41f7816f..cac9e24c38 100644 --- a/specs/exporter-prometheus.spec/pom.xml +++ b/specs/exporter-prometheus.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/guard-jwt.spec/pom.xml b/specs/guard-jwt.spec/pom.xml index cd86beea8a..671f68e2da 100644 --- a/specs/guard-jwt.spec/pom.xml +++ b/specs/guard-jwt.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/metrics-grpc.spec/pom.xml b/specs/metrics-grpc.spec/pom.xml index 59a7ae6fc0..ab56e274cf 100644 --- a/specs/metrics-grpc.spec/pom.xml +++ b/specs/metrics-grpc.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/metrics-http.spec/pom.xml b/specs/metrics-http.spec/pom.xml index 62084f73cd..d54693f8d4 100644 --- a/specs/metrics-http.spec/pom.xml +++ b/specs/metrics-http.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/metrics-stream.spec/pom.xml b/specs/metrics-stream.spec/pom.xml index 7c4866d804..e5f70cb5da 100644 --- a/specs/metrics-stream.spec/pom.xml +++ b/specs/metrics-stream.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml diff --git a/specs/pom.xml b/specs/pom.xml index 68046e563f..54f3482cc4 100644 --- a/specs/pom.xml +++ b/specs/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla zilla - 0.9.51 + 0.9.52 ../pom.xml @@ -26,12 +26,14 @@ binding-tls.spec binding-http.spec binding-grpc.spec + binding-mqtt.spec binding-sse.spec binding-ws.spec binding-kafka.spec binding-http-filesystem.spec binding-http-kafka.spec binding-grpc-kafka.spec + binding-mqtt-kafka.spec binding-sse-kafka.spec binding-kafka-grpc.spec exporter-prometheus.spec @@ -104,6 +106,16 @@ binding-http-filesystem.spec ${project.version} + + ${project.groupId} + binding-mqtt.spec + ${project.version} + + + ${project.groupId} + binding-mqtt-kafka.spec + ${project.version} + ${project.groupId} binding-sse-kafka.spec diff --git a/specs/vault-filesystem.spec/pom.xml b/specs/vault-filesystem.spec/pom.xml index 7eb6b784ef..943d8b6e7c 100644 --- a/specs/vault-filesystem.spec/pom.xml +++ b/specs/vault-filesystem.spec/pom.xml @@ -8,7 +8,7 @@ io.aklivity.zilla specs - 0.9.51 + 0.9.52 ../pom.xml